1#!/usr/bin/env perl 2# 3# Copyright 2004 Mattias Gaertner 4# 5# Search and replace in multiple files with perl syntax 6 7use vars qw/ %opt /; 8use Getopt::Std; 9my $opt_string = 'hvcsinbRf:r:m:'; 10getopts( "$opt_string", \%opt ) or usage(); 11usage() if $opt{h}; 12 13sub usage(){ 14 print STDERR << "EOF"; 15 16Replace strings in files with perl search and replace syntax 17 18usage: $0 [-hRvcnbis] -f text -r replacetext -m filemask file1 file2 ... 19 20 -h : this (help) message 21 -f <text> : find text 22 -r <text> : replace with this text 23 -R : recursive 24 -i : case insensitive 25 -v : verbose 26 -c : print changes 27 -s : write summary 28 -n : simulate, do not change files 29 -b : replace in binary files too 30 -m <filemask> : file mask, useful for recursive 31 32examples: 33 Replace in file1.txt and file2.txt all a with b 34 $0 -vsn -f 'a' -r 'b' file1.txt file2.txt 35 36 Replace in file1.txt all a([0-9]) with b$1 37 $0 -vsn -f 'a([0-9])' -r 'b$1' file1.txt 38 39EOF 40 exit; 41} 42 43usage() unless $opt{f}; # Text needed 44usage() unless $opt{r}; # Replacetext needed 45 46$FindText=$opt{f}; 47$ReplaceText=$opt{r}; 48$FileMask=$opt{m}; 49 50if($opt{v}){ 51 print "Parameters:"; 52 print "FindText=$FindText\n"; 53 print "ReplaceText=$ReplaceText\n"; 54 print "FileMask=$FileMask\n"; 55 print "\n"; 56} 57 58$TotalFiles=0; 59$ChangedFiles=0; 60$TotalLines=0; 61$ChangedLines=0; 62for $Filename(@ARGV){ 63 DoFile($Filename,1); 64} 65if($opt{s}){ 66 print "\nSummary:\n"; 67 print "changed files: $ChangedFiles/$TotalFiles\n"; 68 print "changed lines: $ChangedLines/$TotalLines\n"; 69} 70 71#============================================================================== 72 73sub DoFile(){ 74 (my $Filename,$Level) = @_; 75 76 # skip special files 77 if($Filename eq "."){ return; } 78 if($Filename eq ".."){ return; } 79 80 #print "DoFile $Filename\n"; 81 82 # 83 if(-d $Filename){ 84 if($opt{R}){ 85 if($opt{v}){ 86 #print "Entering directory $Filename\n"; 87 } 88 $Filenames=`ls -1 $Filename`; 89 for $SubFilename(split("\n",$Filenames)){ 90 DoFile($Filename."/".$SubFilename,$Level+1); 91 } 92 if($opt{v}){ 93 #print "Leaving directory $Filename\n"; 94 } 95 } 96 return; 97 } 98 if ((! $opt{b}) && (-B $Filename)){ 99 if($opt{v} && ($Level==1)){ 100 print "Skipping binary file $Filename\n"; 101 } 102 return; 103 } 104 if(($FileMask) && ($Filename !~ /$FileMask/)){ 105 return; 106 } 107 108 my $FilenamePrinted = 0; 109 if($opt{v}){ 110 print "Editing $Filename ...\n"; 111 $FilenamePrinted = 1; 112 } 113 114 $TotalFiles++; 115 open F, "< $Filename" or die "Unable to read file $Filename: $!"; 116 $NewText=""; 117 $LineNumber=1; 118 $FileChanged=0; 119 while ($Line=<F>){ 120 $TotalLines++; 121 $OldLine=$Line; 122 if($opt{i}){ 123 $Line=~s/$FindText/$ReplaceText/goi; 124 } else { 125 $Line=~s/$FindText/$ReplaceText/go; 126 } 127 if($OldLine ne $Line){ 128 $ChangedLines++; 129 $FileChanged=1; 130 if($opt{v} || $opt{c}){ 131 if (! $FilenamePrinted){ 132 print "Editing $Filename ...\n"; 133 $FilenamePrinted = 1; 134 } 135 print "($LineNumber,old):".$OldLine; 136 print "($LineNumber,new):".$Line; 137 } 138 } 139 $NewText.=$Line; 140 $LineNumber++; 141 } 142 if($FileChanged==1){ 143 $ChangedFiles++; 144 } 145 close F; 146 147 if(! $opt{n}){ 148 open F, "> $Filename" or die "Unable to write file $Filename: $!"; 149 print F $NewText; 150 close F; 151 } 152} 153 154# end. 155 156