1#!/vobs/wds/swt/bin/perl 2 3# Copyright (c) 2004, 2005 MySQL AB 4# Use is subject to license terms 5# 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; version 2 of the License. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program; if not, write to the Free Software 17# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 18 19die "Usage: rgrep [-iredblLn] regexp filepat ...\n rgrep -h for help\n" 20 if $#ARGV < $[; 21 22# Written by Piet van Oostrum <piet@cs.ruu.nl> 23# This is really free software 24 25# Mats Lidell added support for gzip. 26# Mats Lidell added support for skipping line numbers. 27 28$nextopt = 1; 29$igncase = ''; 30$regpat = 0; 31$links = 0; 32$error = 0; 33$skipbin = 1; 34$havenl = 1; 35$debug = 0; 36 37do { $regexp = shift (@ARGV); } while &checkopt ($regexp); 38$icreg = $igncase; 39$igncase = ''; 40 41eval 'sub grep_file { 42 while (<F>) { 43 $ln++; 44 if (/$regexp/o' . $icreg .') { 45 print "$file:$ln:" if $havenl; 46 print "$_"; 47 print "\n" if substr($_, -1, 1) ne "\n"; 48 } 49 } 50}'; 51 52for (@ARGV) { 53 if (! &checkopt ($_)) { 54 if ($igncase || $regpat || /[?*[]/ || ! -e) { 55 if ($regpat) { 56 s/#/\\#/g; 57 $_ = "#$_#"; 58 } else { # translate File pattern into regexp 59 $re = '#($|/)'; $save = $_; 60 while (/[[*?+()|.^$#]/) { 61 $re .= $`; 62 $c = $&; 63 $_ = $'; 64 if ($c eq '*') { $c = '[^/]*'; } 65 elsif ($c eq '?') { $c = '[^/]'; } 66 elsif ($c eq '[') { 67 if (/.\]/) { $c = "[$`$&"; $_ = $'; } 68 else { 69 $error++; 70 printf stderr "Illegal filepattern %s\n", $save; 71 } 72 } else { $c = "\\$c"; } 73 $re .= $c; 74 } 75 $_ = "$re$_\$#$igncase"; 76 } 77 print "filepat: $_\n" if $debug; 78 push (@filepat, $_); 79 } 80 else { push (@files, $_); print "file: $_\n" if $debug; } 81 } 82} 83 84exit 1 if $errors ; 85 86if ($#filepat < $[) { 87 eval "sub in_pat {1;}" ; 88} 89else { 90 $subtxt = 'sub in_pat { local ($f) = @_;'; 91 $or = ""; 92 for (@filepat) { 93 $subtxt .= $or . '$f =~ m' . $_; 94 $or = " || "; 95 } 96 $subtxt .= ';};1'; 97 98 if (! eval $subtxt) { 99 print $@; 100 exit 1; 101 } 102} 103 104@files = (".") if $#files < $[; 105 106for $file (@files) { 107 &do_grep ($file); 108} 109 110sub do_grep { 111 local ($file) = @_; 112 local (*F, $ln, $f, $g, @dirfiles); 113 if (-f $file) { 114 if (open (F, $file)) { 115 if (-B F) { # binary file -- may be compressed/compacted/gziped 116 if (($cx1 = getc(F)) eq "\377" && (getc(F) eq "\037")) { 117 open (F, "uncompact < $file|"); 118 if ($skipbin && -B F) { close (F); return; } 119 } 120 elsif ($cx1 eq "\037" && (($cx2 = getc(F)) eq "\235")) { 121 open (F, "uncompress < $file|"); 122 if ($skipbin && -B F) { close (F); return; } 123 } 124 elsif ($cx1 eq "\037" && $cx2 eq "\213") { 125 open (F, "gzip -d < $file|"); 126 if ($skipbin && -B F) { close (F); return; } 127 } 128 elsif ($skipbin) { 129 close (F); return; 130 } 131 } 132 print "Reading $file\n" if $debug; 133 &grep_file; 134 } else { 135 print stderr "Cannot open $file\n"; 136 } 137 } 138 elsif (-d $file) { 139 print "Entering $file\n" if $debug; 140 if (opendir (F, $file)) { 141 @dirfiles = readdir (F); 142 closedir (F); 143 for $f (@dirfiles) { 144 next if ($f eq '.' || $f eq '..'); 145 $g = "$file/$f"; 146 next if (-l $g && ($links < 1 || $links == 1 && -d $g)); 147 if (-f $g && &in_pat ($g) || -d _) { 148 &do_grep ($g); 149 } 150 } 151 } else { 152 print stderr "Can't open $file\n"; 153 } 154 } 155} 156 157sub checkopt { 158 local ($_) = $_[0]; 159 if (/^-/ && $nextopt) { 160 $nextopt = 1; 161 @opt = split (/-*/,$_); shift (@opt); 162 for $opt (@opt) { 163 if ($opt eq 'i') { $igncase = 'i'; } 164 elsif ($opt eq 'd') { $debug = 1; } 165 elsif ($opt eq 'l') { $links = 1; } 166 elsif ($opt eq 'L') { $links = 2; } 167 elsif ($opt eq 'b') { $skipbin = 0; } 168 elsif ($opt eq 'r') { $regpat = 1; } 169 elsif ($opt eq 'e') { $nextopt = 0; } 170 elsif ($opt eq 'n') { $havenl = 0; } 171 elsif ($opt eq 'h' || $opt eq 'H') { & help; } 172 else { $error++; printf stderr "Unknown option -%s\n", $opt; } 173 } 174 return 1; 175 } 176 $nextopt = 1; 177 return 0; 178} 179 180sub help { 181 print <<'HELP'; exit 0; 182Usage: rgrep [-iredblL] regexp filepat ... 183 regexp = perl regular expression to search 184 filepat ... = a list of files and directories to be searched or 185 file patterns to match filenames. 186 filepat will be interpreted as file or directory name if it exists 187 as such, and does not contain the metacharacters [ ] ? or *. After 188 the options -i and -r all filepats will be considered patterns. 189 rgrep will search all files in any of the directories given (and its 190 subdirectories) that match any of the filepats, except binary files. 191 Compressed files will be searched in uncompressed form. 192 Note: filepats may contain / contrary to find usage. 193 -b Don't skip binary files. 194 -i Ignore case, either in the regexp or in filename matching (depending 195 on the location). Before the regexp only applies to the regexp, 196 otherwise to the filepats following it. 197 -r The following filepats are treated as real perl regexps rather than 198 shell style filename patterns. In this case / is not a special 199 character, i.e. it is matched by . and matching is not anchored (you 200 must supply ^ and $ yourself). E.g. a.b matches the file /xa/by/zz. 201 -l Do follow symbolic links only for files (default is do not follow). 202 -L Do follow symbolic links for files and directories. 203 -e Do not interpret following argument as option. Useful if regexp or 204 filepat starts with a -. 205 -d Debugging: Give a lot of output on what happens. 206 -n Don't precede each line by its relative line number in the file. 207 -h print this message and exit. 208Piet van Oostrum <piet@cs.ruu.nl> 209HELP 210} 211