#!/usr/bin/perl # # Copyright 2004 Mattias Gaertner # # Search and replace in multiple files with perl syntax use vars qw/ %opt /; use Getopt::Std; my $opt_string = 'hvcsinbRf:r:m:'; getopts( "$opt_string", \%opt ) or usage(); usage() if $opt{h}; sub usage(){ print STDERR << "EOF"; Replace strings in files with perl search and replace syntax usage: $0 [-hRvcnbis] -f text -r replacetext -m filemask file1 file2 ... -h : this (help) message -f : find text -r : replace with this text -R : recursive -i : case insensitive -v : verbose -c : print changes -s : write summary -n : simulate, do not change files -b : replace in binary files too -m : file mask, useful for recursive examples: Replace in file1.txt and file2.txt all a with b $0 -vsn -f 'a' -r 'b' file1.txt file2.txt Replace in file1.txt all a([0-9]) with b$1 $0 -vsn -f 'a([0-9])' -r 'b$1' file1.txt EOF exit; } usage() unless $opt{f}; # Text needed usage() unless $opt{r}; # Replacetext needed $FindText=$opt{f}; $ReplaceText=$opt{r}; $FileMask=$opt{m}; if($opt{v}){ print "Parameters:"; print "FindText=$FindText\n"; print "ReplaceText=$ReplaceText\n"; print "FileMask=$FileMask\n"; print "\n"; } $TotalFiles=0; $ChangedFiles=0; $TotalLines=0; $ChangedLines=0; for $Filename(@ARGV){ DoFile($Filename,1); } if($opt{s}){ print "\nSummary:\n"; print "changed files: $ChangedFiles/$TotalFiles\n"; print "changed lines: $ChangedLines/$TotalLines\n"; } #============================================================================== sub DoFile(){ (my $Filename,$Level) = @_; # skip special files if($Filename eq "."){ return; } if($Filename eq ".."){ return; } #print "DoFile $Filename\n"; # if(-d $Filename){ if($opt{R}){ if($opt{v}){ #print "Entering directory $Filename\n"; } $Filenames=`ls -1 $Filename`; for $SubFilename(split("\n",$Filenames)){ DoFile($Filename."/".$SubFilename,$Level+1); } if($opt{v}){ #print "Leaving directory $Filename\n"; } } return; } if ((! $opt{b}) && (-B $Filename)){ if($opt{v} && ($Level==1)){ print "Skipping binary file $Filename\n"; } return; } if(($FileMask) && ($Filename !~ /$FileMask/)){ return; } my $FilenamePrinted = 0; if($opt{v}){ print "Editing $Filename ...\n"; $FilenamePrinted = 1; } $TotalFiles++; open F, "< $Filename" or die "Unable to read file $Filename: $!"; $NewText=""; $LineNumber=1; $FileChanged=0; while ($Line=){ $TotalLines++; $OldLine=$Line; if($opt{i}){ $Line=~s/$FindText/$ReplaceText/goi; } else { $Line=~s/$FindText/$ReplaceText/go; } if($OldLine ne $Line){ $ChangedLines++; $FileChanged=1; if($opt{v} || $opt{c}){ if (! $FilenamePrinted){ print "Editing $Filename ...\n"; $FilenamePrinted = 1; } print "($LineNumber,old):".$OldLine; print "($LineNumber,new):".$Line; } } $NewText.=$Line; $LineNumber++; } if($FileChanged==1){ $ChangedFiles++; } close F; if(! $opt{n}){ open F, "> $Filename" or die "Unable to write file $Filename: $!"; print F $NewText; close F; } } # end.