Main Page Content
Replacing Text In Multiple Files With Perl
Have you ever needed to change the text in a
bunch of files quickly? You could open each fileand then do a search-and-replace. This processcan be time-consuming, tedious, and error-prone.So instead, let's automate this task withPerl.The
Code#!/usr/local/bin/perl## Replaces a string within multiple files# specified on the command line$mv = '/bin/mv';
$op = shift || die("Usage: $0 perlexpr [filenames]
");if (!@ARGV) {
@ARGV = <STDIN>; chop(@ARGV);}foreach $file (@ARGV) {
if (!-f $file) { print "Skipping non-regular file: $file"; next; } if (-B $file) { print "Skipping binary file: $file"; next; }$outfile = "/usr/tmp/$file.$$";
open(FILE, $file) ||
die("Couldn't open $file: $!"); undef $/; $_ = <FILE>; close(FILE);if (eval $op) {
open(OFILE, "> $outfile") || die("Couldn't open $outfile: $!"); print OFILE; close(OFILE);system($mv, '-f', $file, "$file.bak");
system($mv, '-f', $outfile, $file);print "File changed: $file
"; } else { print "No change to file: $file"; }}exit(0);
The Explanation
Save the above code into a file called
replace. Make sure that thepermissions are set correctly so that you canexecute the script. Also check to make sure thatyour Perl interpreter is in /usr/local/bin. IfPerl is somewhere else, you'll need to change thefirst line to point to where Perl is installed onyour system. Finally, check to make sure thatyour mv executable is in /binwhich it should be. If not, you'll need to changeline 6, $mv = '/bin/mv'; to point to the correct location of the executable.To use the script you would type:
replace perlexpr[files]
where perlexpr is the
substitution operator, i.e., s///. You canactually pass any Perl expression through toperlexpr allowing you to do morecomplex text substitutions. If you decide tothat, however, make sure that your expressionleaves the block with a non-zero value if you want the change to take place. It's easiest to makethis value the number of replacements thatactually occurred. The filesargument is a list of filesname that you want tochange. You can leave this argument out and thescript will take a list of names from STDIN.The script works by reading in each text file
that is passed to it and evaluating the Perlexpression that is supplied on the command-line.If the expression evaluates to TRUE, it creates atemporary file containing the changes, makes abackup of the original file(filename.bak), and then copies thechanged file over top of the original file. Also,since the script reads the entire file into asingle scalar variable, you'll probably want touse the /g modifier to any substitution commandsthat you pass in; this will ensure that multipleoccurrences are replaced and not just the firstone.The Examples
Your company has changed its name from 'Get
Rich Quick Corp.' to 'Suckers Are Us' and you need to change all your Web pages to reflect this.replace 's/Get Rich QuickCorp\./Suckers Are Us/g' *
The new guy in your office has started
using .htm in all of his links while the files are actually end in .html.replace 's/\.htm\"/\.html\"/g'*.htm
You can then use your
renamescript to change the file suffixes from .htmto .html.Note: This assumes that your
links end with a double quotation mark and that.htm" does not appear anywhere but in alink.You want to highlight all references to my
name in your files.replace 's!Dean Mah!<strong>DeanMah</strong>!g' *
The standard warning applies here when using
regular expressions, make your expressions asspecific as possible, otherwise they are bound tomatch something that you didn't want it to. To besafe, you should compare the original file withthe changed file using something likediff to make sure that only thechanges that you wanted occurred.If you have any problems or questions about
this script, you can e-mail them to me at:dmah@vox.org.