How can I do bulk search and replace perl?

I have the following script that takes an input file, an output file and replaces the line in the input file with some other line and writes the output file.

I want to change the script to go through the file directory, that is, instead of asking for input and output files, the script should take as an argument the path to the directory, such as C: \ temp \ allFilesTobeReplaced \ and find the line x and replace it with y for all files under this path to the directory and write out the same files.

How to do it?

Thanks.

$file=$ARGV[0]; open(INFO,$file); @lines=<INFO>; print @lines; open(INFO,">c:/filelist.txt"); foreach $file (@lines){ #print "$file\n"; print INFO "$file"; } #print "Input file name: "; #chomp($infilename = <STDIN>); if ($ARGV[0]){ $file= $ARGV[0] } print "Output file name: "; chomp($outfilename = <STDIN>); print "Search string: "; chomp($search = <STDIN>); print "Replacement string: "; chomp($replace = <STDIN>); open(INFO,$file); @lines=<INFO>; open(OUT,">$outfilename") || die "cannot create $outfilename: $!"; foreach $file (@lines){ # read a line from file IN into $_ s/$search/$replace/g; # change the lines print OUT $_; # print that line to file OUT } close(IN); close(OUT); 
+6
replace perl bulk
source share
5 answers

Using a single perl liner

 perl -pi -e 's/original string/new string/' filename 

can be combined with File::Find to give the following single script (this is the template that I use for many such operations).

 use File::Find; # search for files down a directory hierarchy ('.' taken for this example) find(\&wanted, "."); sub wanted { if (-f $_) { # for the files we are interested in call edit_file(). edit_file($_); } } sub edit_file { my ($filename) = @_; # you can re-create the one-liner above by localizing @ARGV as the list of # files the <> will process, and localizing $^I as the name of the backup file. local (@ARGV) = ($filename); local($^I) = '.bak'; while (<>) { s/original string/new string/g; } continue { print; } } 
+11
source share

You can do this with -i param:

Just process all the files as usual, but include -i.bak:

 #!/usr/bin/perl -i.bak while ( <> ) { s/before/after/; print; } 

This should process each file and rename the original in original.bak. And of course, you can do it as a one-line, mentioned by @Jamie Cook

+2
source share

try it

 #!/usr/bin/perl -w @files = <*>; foreach $file (@files) { print $file . '\n'; } 

Take also a look at glob in Perl:

+1
source share

I know that you can use simple single-line Perl from the command line, where filename can be a single file name or a list of file names. You could probably combine this with a bgy answer to get the desired effect:

 perl -pi -e 's/original string/new string/' filename 

And I know this is commonplace, but it is very similar to sed if you can use gnu tools:

 for i in `find ./allFilesTobeReplaced`; do sed -is/original string/new string/g $i; done 
+1
source share

perl -pi -e '# OLD # NEW # g' filename. You can replace the file name with a template suitable for your file list.

-one
source share

All Articles