1 #!/usr/local/bin/perl -w
4 ##############################################################################
8 ## Jeffrey Friedl (jfriedl@omron.co.jp), Dec 1994.
9 ## Copyright 19.... ah hell, just take it.
12 ## A combo of find and grep -- more or less do a 'grep' on a whole
13 ## directory tree. Fast, with lots of options. Much more powerful than
14 ## the simple "find ... | xargs grep ....". Has a full man page.
15 ## Powerfully customizable.
17 ## This file is big, but mostly comments and man page.
19 ## See man page for usage info.
20 ## Return value: 2=error, 1=nothing found, 0=something found.
23 $version = "950918.5";
26 ## Changed all 'sysread' to 'read' because Linux perl's don't seem
33 ## Added -nice (due to Lionel Cons <Lionel.Cons@cern.ch>)
34 ## Removed any leading "./" from name.
35 ## Added default flags for ~/.search, including TTY, -nice, -list, etc.
36 ## Program name now has path removed when printed in diagnostics.
37 ## Added simple tilde-expansion to -dir arg.
38 ## Added -dskip, etc. Fixed -iregex bug.
39 ## Changed -dir to be additive, adding -ddir.
40 ## Now screen out devices, pipes, and sockets.
41 ## More tidying and lots of expanding of the man page
50 if (exists $ENV{'HOME'}) {
51 $rc_file = join('/', $ENV{'HOME'}, ".search");
59 ## Make sure we've got a regex.
60 ## Don't need one if -find or -showrc was specified.
61 $!=2, die "expecting regex arguments.\n"
62 if $FIND_ONLY == 0 && $showrc == 0 && @ARGV == 0;
64 &prepare_to_search($rc_file);
66 &import_program if !defined &dodir; ## BIG key to speed.
68 ## do search while there are directories to be done.
69 &dodir(shift(@todo)) while @todo;
71 &clear_message if $VERBOSE && $STDERR_IS_TTY;
73 ###############################################################################
77 ## initialize variables that might be reset by command-line args
78 $DOREP=0; ## set true by -dorep (redo multi-hardlink files)
79 $DOREP=1 if $^O eq 'MSWin32';
80 $DO_SORT=0; ## set by -sort (sort files in a dir before checking)
81 $FIND_ONLY=0; ## set by -find (don't search files)
82 $LIST_ONLY=0; ## set true by -l (list filenames only)
83 $NEWER=0; ## set by -newer, "-mtime -###"
84 $NICE=0; ## set by -nice (print human-readable output)
85 $NOLINKS=0; ## set true by -nolinks (don't follow symlinks)
86 $OLDER=0; ## set by -older, "-mtime ###"
87 $PREPEND_FILENAME=1; ## set false by -h (don't prefix lines with filename)
88 $REPORT_LINENUM=0; ## set true by -n (show line numbers)
89 $VERBOSE=0; ## set to a value by -v, -vv, etc. (verbose messages)
90 $WHY=0; ## set true by -why, -vvv+ (report why skipped)
91 $XDEV=0; ## set true by -xdev (stay on one filesystem)
92 $all=0; ## set true by -all (don't skip many kinds of files)
93 $iflag = ''; ## set to 'i' by -i (ignore case);
94 $norc=0; ## set by -norc (don't load rc file)
95 $showrc=0; ## set by -showrc (show what happens with rc file)
96 $underlineOK=0; ## set true by -u (watch for underline stuff)
97 $words=0; ## set true by -w (match whole-words only)
98 $DELAY=0; ## inter-file delay (seconds)
99 $retval=1; ## will set to 0 if we find anything.
101 ## various elements of stat() that we might access
106 $VV_PRINT_COUNT = 50; ## with -vv, print every VV_PRINT_COUNT files, or...
107 $VV_SIZE = 1024*1024; ## ...every VV_SIZE bytes searched
108 $vv_print = $vv_size = 0; ## running totals.
110 ## set default options, in case the rc file wants them
111 $opt{'TTY'}= 1 if -t STDOUT;
113 ## want to know this for debugging message stuff
114 $STDERR_IS_TTY = -t STDERR ? 1 : 0;
115 $STDERR_SCREWS_STDOUT = ($STDERR_IS_TTY && -t STDOUT) ? 1 : 0;
117 $0 =~ s,.*/,,; ## clean up $0 for any diagnostics we'll be printing.
125 while (@ARGV && $ARGV[0] =~ m/^-/)
129 if ($arg eq '-version' || ($VERBOSE && $arg eq '-help')) {
130 print qq/Jeffrey's file search, version "$version".\n/;
131 exit(0) unless $arg eq '-help';
133 if ($arg eq '-help') {
134 print <<INLINE_LITERAL_TEXT;
135 usage: $0 [options] [-e] [PerlRegex ....]
136 OPTIONS TELLING *WHERE* TO SEARCH:
137 -dir DIR start search at the named directory (default is current dir).
138 -xdev stay on starting file system.
139 -sort sort the files in each directory before processing.
140 -nolinks don't follow symbolic links.
141 OPTIONS TELLING WHICH FILES TO EVEN CONSIDER:
142 -mtime # consider files modified > # days ago (-# for < # days old)
143 -newer FILE consider files modified more recently than FILE (also -older)
144 -name GLOB consider files whose name matches pattern (also -regex).
145 -skip GLOB opposite of -name: identifies files to not consider.
146 -path GLOB like -name, but for files whose whole path is described.
147 -dpath/-dregex/-dskip versions for selecting or pruning directories.
148 -all don't skip any files marked to be skipped by the startup file.
149 -x<SPECIAL> (see manual, and/or try -showrc).
150 -why report why a file isn't checked (also implied by -vvvv).
151 OPTIONS TELLING WHAT TO DO WITH FILES THAT WILL BE CONSIDERED:
152 -f | -find just list files (PerlRegex ignored). Default is to grep them.
153 -ff | -ffind Does a faster -find (implies -find -all -dorep)
154 OPTIONS CONTROLLING HOW THE SEARCH IS DONE (AND WHAT IS PRINTED):
155 -l | -list only list files with matches, not the lines themselves.
156 -nice | -nnice print more "human readable" output.
157 -n prefix each output line with its line number in the file.
158 -h don't prefix output lines with file name.
159 -u also look "inside" manpage-style underlined text
160 -i do case-insensitive searching.
161 -w match words only (as defined by perl's \\b).
163 -v, -vv, -vvv various levels of message verbosity.
164 -e end of options (in case a regex looks like an option).
165 -showrc show what the rc file sets, then exit.
166 -norc don't load the rc file.
167 -dorep check files with multiple hard links multiple times.
169 print "Use -v -help for more verbose help.\n" unless $VERBOSE;
170 print "This script file is also a man page.\n" unless $stripped;
171 print <<INLINE_LITERAL_TEXT if $VERBOSE;
173 If -f (or -find) given, PerlRegex is optional and ignored.
174 Otherwise, will search for files with lines matching any of the given regexes.
176 Combining things like -name and -mtime implies boolean AND.
177 However, duplicating things (such as -name '*.c' -name '*.txt') implies OR.
179 -mtime may be given floating point (i.e. 1.5 is a day and a half).
180 -iskip/-idskip/-ipath/... etc are case-insensitive versions.
182 If any letter in -newer/-older is upper case, "or equal" is
183 inserted into the test.
188 $DOREP=1, next if $arg eq '-dorep'; ## do repeats
189 $DO_SORT=1, next if $arg eq '-sort'; ## sort files
190 $NOLINKS=1, next if $arg eq '-nolinks'; ## no sym. links
191 $PREPEND_FILENAME=0, next if $arg eq '-h'; ## no filename prefix
192 $REPORT_LINENUM=1, next if $arg eq '-n'; ## show line numbers
193 $WHY=1, next if $arg eq '-why'; ## tell why skipped
194 $XDEV=1, next if $arg eq '-xdev'; ## don't leave F.S.
195 $all=1,$opt{'-all'}=1,next if $arg eq '-all'; ## don't skip *.Z, etc
196 $iflag='i', next if $arg eq '-i'; ## ignore case
197 $norc=1, next if $arg eq '-norc'; ## don't load rc file
198 $showrc=1, next if $arg eq '-showrc'; ## show rc file
199 $underlineOK=1, next if $arg eq '-u'; ## look throuh underln.
200 $words=1, next if $arg eq '-w'; ## match "words" only
201 &strip if $arg eq '-strip'; ## dump this program
202 last if $arg eq '-e';
203 $DELAY=$1, next if $arg =~ m/-delay(\d+)/;
205 $FIND_ONLY=1, next if $arg =~/^-f(ind)?$/;## do "find" only
207 $FIND_ONLY=1, $DOREP=1, $all=1,
208 next if $arg =~/^-ff(ind)?$/;## fast -find
209 $LIST_ONLY=1,$opt{'-list'}=1,
210 next if $arg =~/^-l(ist)?$/;## only list files
212 if ($arg =~ m/^-(v+)$/) { ## verbosity
213 $VERBOSE =length($1);
214 foreach $len (1..$VERBOSE) { $opt{'-'.('v' x $len)}=1 }
217 if ($arg =~ m/^-(n+)ice$/) { ## "nice" output
219 foreach $len (1..$NICE) { $opt{'-'.('n' x $len).'ice'}=1 }
223 if ($arg =~ m/^-(i?)(d?)skip$/) {
224 local($i) = $1 eq 'i';
225 local($d) = $2 eq 'd';
226 $! = 2, die qq/$0: expecting glob arg to -$arg\n/ unless @ARGV;
227 foreach (split(/\s+/, shift @ARGV)) {
240 if ($arg =~ m/^-(i?)(d?)(regex|path|name)$/) {
241 local($i) = $1 eq 'i';
242 $! = 2, die qq/$0: expecting arg to -$arg\n/ unless @ARGV;
243 foreach (split(/\s+/, shift @ARGV)) {
244 $iname{join(',', $arg, $_)}=1 if $i;
245 $name{join(',', $arg, $_)}=1;
250 if ($arg =~ m/^-d?dir$/) {
252 $! = 2, die qq/$0: expecting filename arg to -$arg\n/ unless @ARGV;
253 $start = shift(@ARGV);
254 $start =~ s#^~(/+|$)#$ENV{'HOME'}$1# if defined $ENV{'HOME'};
255 $! = 2, die qq/$0: can't find ${arg}'s "$start"\n/ unless -e $start;
256 $! = 2, die qq/$0: ${arg}'s "$start" not a directory.\n/ unless -d _;
257 undef(@todo), $opt{'-ddir'}=1 if $arg eq '-ddir';
262 if ($arg =~ m/^-(new|old)er$/i) {
263 $! = 2, die "$0: expecting filename arg to -$arg\n" unless @ARGV;
264 local($file, $time) = shift(@ARGV);
265 $! = 2, die qq/$0: can't stat -${arg}'s "$file"./
266 unless $time = (stat($file))[$STAT_MTIME];
267 local($upper) = $arg =~ tr/A-Z//;
268 if ($arg =~ m/new/i) {
269 $time++ unless $upper;
270 $NEWER = $time if $NEWER < $time;
272 $time-- unless $upper;
273 $OLDER = $time if $OLDER == 0 || $OLDER > $time;
278 if ($arg =~ m/-mtime/) {
279 $! = 2, die "$0: expecting numerical arg to -$arg\n" unless @ARGV;
280 local($days) = shift(@ARGV);
281 $! = 2, die qq/$0: inappropriate arg ($days) to $arg\n/ if $days==0;
284 local($time) = $^T + $days;
285 $NEWER = $time if $NEWER < $time;
287 local($time) = $^T - $days;
288 $OLDER = $time if $OLDER == 0 || $OLDER > $time;
293 ## special user options
294 if ($arg =~ m/^-x(.+)/) {
295 foreach (split(/[\s,]+/, $1)) { $user_opt{$_} = $opt{$_}= 1; }
299 $! = 2, die "$0: unknown arg [$arg]\n";
304 ## Given a filename glob, return a regex.
305 ## If the glob has no globbing chars (no * ? or [..]), then
306 ## prepend an effective '*' to it.
311 local(@parts) = $glob =~ m/\\.|[*?]|\[]?[^]]*]|[^[\\*?]+/g;
314 if ($_ eq '*' || $_ eq '?') {
316 $trueglob=1; ## * and ? are a real glob
317 } elsif (substr($_, 0, 1) eq '[') {
318 $trueglob=1; ## [..] is a real glob
320 s/^\\//; ## remove any leading backslash;
321 s/\W/\\$&/g; ## now quote anything dangerous;
324 unshift(@parts, '.*') unless $trueglob;
325 join('', '^', @parts, '$');
328 sub prepare_to_search
330 local($rc_file) = @_;
332 $HEADER_BYTES=0; ## Might be set nonzero in &read_rc;
333 $last_message_length = 0; ## For &message and &clear_message.
335 &read_rc($rc_file, $showrc) unless $norc;
338 $NEXT_DIR_ENTRY = $DO_SORT ? 'shift @files' : 'readdir(DIR)';
339 $WHY = 1 if $VERBOSE > 3; ## Arg -vvvv or above implies -why.
340 @todo = ('.') if @todo == 0; ## Where we'll start looking
342 ## see if any user options were specified that weren't accounted for
343 foreach $opt (keys %user_opt) {
344 next if defined $seen_opt{$opt};
345 warn "warning: -x$opt never considered.\n";
348 die "$0: multiple time constraints exclude all possible files.\n"
349 if ($NEWER && $OLDER) && ($NEWER > $OLDER);
352 ## Process any -skip/-iskip args that had been given
355 foreach $glob (keys %skip) {
356 $i = defined($iskip{$glob}) ? 'i': '';
357 push(@skip_test, '$name =~ m/'. &glob_to_regex($glob). "/$i");
360 $SKIP_TEST = join('||',@skip_test);
363 $DO_SKIP_TEST = $SKIP_TEST = 0;
367 ## Process any -dskip/-idskip args that had been given
370 foreach $glob (keys %dskip) {
371 $i = defined($idskip{$glob}) ? 'i': '';
372 push(@dskip_test, '$name =~ m/'. &glob_to_regex($glob). "/$i");
375 $DSKIP_TEST = join('||',@dskip_test);
378 $DO_DSKIP_TEST = $DSKIP_TEST = 0;
383 ## Process any -name, -path, -regex, etc. args that had been given.
387 foreach $key (keys %name) {
388 local($type, $pat) = split(/,/, $key, 2);
389 local($i) = defined($iname{$key}) ? 'i' : '';
390 if ($type =~ /regex/) {
392 $test = "\$name =~ m!^$pat\$!$i";
394 local($var) = $type eq 'name' ? '$name' : '$file';
395 $test = "$var =~ m/". &glob_to_regex($pat). "/$i";
397 if ($type =~ m/^-i?d/) {
398 push(@dname_test, $test);
400 push(@name_test, $test);
404 $GLOB_TESTS = join('||', @name_test);
408 $GLOB_TESTS = $DO_GLOB_TESTS = 0;
411 $DGLOB_TESTS = join('||', @dname_test);
414 $DGLOB_TESTS = $DO_DGLOB_TESTS = 0;
419 ## Process any 'magic' things from the startup file.
421 if (@magic_tests && $HEADER_BYTES) {
422 ## the $magic' one is for when &dodir is not inlined
423 $tests = join('||',@magic_tests);
424 $MAGIC_TESTS = " { package magic; \$val = ($tests) }";
432 ## Prepare regular expressions.
439 ## need to have $* set, but perl5 just won''t shut up about it.
448 ## Until I figure out a better way to deal with it,
449 ## We have to worry about a regex like [^xyz] when doing $LIST_ONLY.
450 ## Such a regex *will* match \n, and if I'm pulling in multiple
451 ## lines, it can allow lines to match that would otherwise not match.
453 ## Therefore, if there is a '[^' in a regex, we can NOT take a chance
454 ## an use the fast listonly.
456 $CAN_USE_FAST_LISTONLY = $LIST_ONLY;
459 local($underline_glue) = ($] >= 5) ? '(:?_\cH)?' : '(_\cH)?';
461 $regex = shift(@ARGV);
463 ## If watching for underlined things too, add another regex.
466 if ($regex =~ m/[?*+{}()\\.|^\$[]/) {
467 warn "$0: warning, can't underline-safe ``$regex''.\n";
469 $regex = join($underline_glue, split(//, $regex));
473 ## If nothing special in the regex, just use index...
474 ## is quite a bit faster.
475 if (($iflag eq '') && ($words == 0) &&
476 $regex !~ m/[?*+{}()\\.|^\$[]/)
478 push(@regex_tests, "(index(\$_, q+$regex+)>=0)");
481 $regex =~ s#[\$\@\/]\w#\\$&#;
483 if ($regex =~ m/\|/) {
484 ## could be dangerous -- see if we can wrap in parens.
485 if ($regex =~ m/\\\d/) {
486 warn "warning: -w and a | in a regex is dangerous.\n"
488 $regex = join($regex, '(', ')');
491 $regex = join($regex, '\b', '\b');
493 $CAN_USE_FAST_LISTONLY = 0 if substr($regex, "[^") >= 0;
494 push(@regex_tests, "m/$regex/$iflag$mflag");
497 ## If we're done, but still have @extra to do, get set for that.
498 if (@ARGV == 0 && @extra) {
499 @ARGV = @extra; ## now deal with the extra stuff.
500 $underlineOK = 0; ## but no more of this.
501 undef @extra; ## or this.
505 $REGEX_TEST = join('||', @regex_tests);
506 ## print STDERR $REGEX_TEST, "\n"; exit;
508 ## must be doing -find -- just give something syntactically correct.
514 ## Make sure we can read the first item(s).
516 foreach $start (@todo) {
517 $! = 2, die qq/$0: can't stat "$start"\n/
518 unless ($dev,$inode) = (stat($start))[$STAT_DEV,$STAT_INODE];
520 if (defined $dir_done{"$dev,$inode"}) {
521 ## ignore the repeat.
522 warn(qq/ignoring "$start" (same as "$dir_done{"$dev,$inode"}").\n/)
527 ## if -xdev was given, remember the device.
528 $xdev{$dev} = 1 if $XDEV;
530 ## Note that we won't want to do it again
531 $dir_done{"$dev,$inode"} = $start;
537 ## See the comment above the __END__ above the 'sub dodir' below.
542 print STDERR "$0: internal error (@_)\n";
546 ## Read from data, up to next __END__. This will be &dodir.
547 local($/) = "\n__END__";
551 $prog =~ s/\beval\b//g; ## remove any 'eval'
553 ## Inline uppercase $-variables by their current values.
555 $prog =~ s/\$([A-Z][A-Z0-9_]{2,}\b)/
556 &bad($1) if !defined ${$main::{$1}}; ${$main::{$1}};/eg;
558 $prog =~ s/\$([A-Z][A-Z0-9_]{2,}\b)/local(*VAR) = $_main{$1};
559 &bad($1) if !defined $VAR; $VAR;/eg;
562 eval $prog; ## now do it. This will define &dodir;
563 $!=2, die "$0 internal error: $@\n" if $@;
566 ###########################################################################
569 ## Read the .search file:
570 ## Blank lines and lines that are only #-comments ignored.
571 ## Newlines may be escaped to create long lines
572 ## Other lines are directives.
574 ## A directive may begin with an optional tag in the form <...>
575 ## Things inside the <...> are evaluated as with:
576 ## <(this || that) && must>
578 ## -xmust -xthis or -xmust -xthat
579 ## were specified on the command line (order doesn't matter, though)
580 ## A directive is not done if there is a tag and it's false.
581 ## Any characters but whitespace and &|()>,! may appear after an -x
582 ## (although "-xdev" is special). -xmust,this is the same as -xmust -xthis.
583 ## Something like -x~ would make <~> true, and <!~> false.
585 ## Directives are in the form:
587 ## magic : NUMBYTES : EXPR
590 ## The STRING is parsed like a Bourne shell command line, and the
591 ## options are used as if given on the command line.
592 ## No comments are allowed on 'option' lines.
594 ## # skip objects and libraries
595 ## option: -skip '.o .a'
596 ## # skip emacs *~ and *# files, unless -x~ given:
597 ## <!~> option: -skip '~ #'
600 ## EXPR can be pretty much any perl (comments allowed!).
601 ## If it evaluates to true for any particular file, it is skipped.
602 ## The only info you'll have about a file is the variable $H, which
603 ## will have at least the first NUMBYTES of the file (less if the file
604 ## is shorter than that, of course, and maybe more). You'll also have
605 ## any variables you set in previous 'magic' lines.
607 ## magic: 6 : ($x6 = substr($H, 0, 6)) eq 'GIF87a'
608 ## magic: 6 : $x6 eq 'GIF89a'
610 ## magic: 6 : (($x6 = substr($H, 0, 6)) eq 'GIF87a' ## old gif \
611 ## || $x6 eq 'GIF89a' ## new gif
612 ## (the above two sets are the same)
613 ## ## Check the first 32 bytes for "binarish" looking bytes.
614 ## ## Don't blindly dump on any high-bit set, as non-ASCII text
615 ## ## often has them set. \x80 and \xff seem to be special, though.
616 ## ## Require two in a row to not get things like perl's $^T.
617 ## ## This is known to get *.Z, *.gz, pkzip, *.elc and about any
618 ## ## executable you'll find.
619 ## magic: 32 : $H =~ m/[\x00-\x06\x10-\x1a\x1c-\x1f\x80\xff]{2}/
623 local($file, $show) = @_;
624 local($line_num, $ln, $tag) = 0;
625 local($use_default, @default) = 0;
627 { package magic; $^W= 0; } ## turn off warnings for when we run EXPR's
629 unless (open(RC, "$file")) {
631 $file = "<internal default startup file>";
632 ## no RC file -- use this default.
633 @default = split(/\n/,<<'--------INLINE_LITERAL_TEXT');
634 magic: 32 : $H =~ m/[\x00-\x06\x10-\x1a\x1c-\x1f\x80\xff]{2}/
635 option: -skip '.a .elc .gz .o .pbm .xbm .dvi'
636 option: -iskip '.com .exe .lib .pdb .tarz .zip .z .lzh .jpg .jpeg .gif .uu'
637 <!~> option: -skip '~ #'
638 --------INLINE_LITERAL_TEXT
642 ## Make an eval error pretty.
644 sub clean_eval_error {
646 s/ in file \(eval\) at line \d+,//g; ## perl4-style error
647 s/ at \(eval \d+\) line \d+,//g; ## perl5-style error
648 $_ = $` if m/\n/; ## remove all but first line
652 print "reading RC file: $file\n" if $show;
654 while (defined($_ = ($use_default ? shift(@default) : <RC>))) {
655 $ln = ++$line_num; ## note starting line num.
656 $_ .= <RC>, $line_num++ while s/\\\n?$/\n/; ## allow continuations
657 next if /^\s*(#.*)?$/; ## skip blank or comment-only lines.
660 ## look for an initial <...> tag.
661 if (s/^\s*<([^>]*)>//) {
662 ## This simple s// will make the tag ready to eval.
663 ($tag = $msg = $1) =~
665 $seen_opt{$&}=1; ## note seen option
666 "defined(\$opt{q>$&>})" ## (q>> is safe quoting here)
669 ## see if the tag is true or not, abort this line if not.
670 $dothis = (eval $tag);
671 $!=2, die "$file $ln <$msg>: $_".&clean_eval_error($@) if $@;
674 $msg =~ s/[^\s&|(!)]+/-x$&/;
675 $msg =~ s/\s*!\s*/ no /g;
676 $msg =~ s/\s*&&\s*/ and /g;
677 $msg =~ s/\s*\|\|\s*/ or /g;
678 $msg =~ s/^\s+//; $msg =~ s/\s+$//;
679 $do = $dothis ? "(doing because $msg)" :
686 if (m/^\s*option\s*:\s*/) {
687 next if $all && !$show; ## -all turns off these checks;
691 print " $do option: $_\n" if $show;
692 local($0) = "$0 ($file)"; ## for any error message.
696 ## Parse $_ as a Bourne shell line -- fill @ARGV
700 push(@ARGV, $this) if defined $this;
704 $this = '' if !defined $this;
705 $this .= $1 while s/^'([^']*)'// ||
709 die "$file $ln: error parsing $orig at $_\n" if m/^\S/;
711 push(@ARGV, $this) if defined $this;
713 die qq/$file $ln: unused arg "@ARGV".\n/ if @ARGV;
717 if (m/^\s*magic\s*:\s*(\d+)\s*:\s*/) {
718 next if $all && !$show; ## -all turns off these checks;
719 local($bytes, $check) = ($1, $');
722 $check =~ s/\n?$/\n/;
723 print " $do contents: $check";
725 ## Check to make sure the thing at least compiles.
726 eval "package magic; (\$H = '1'x \$main'bytes) && (\n$check\n)\n";
727 $! = 2, die "$file $ln: ".&clean_eval_error($@) if $@;
729 $HEADER_BYTES = $bytes if $bytes > $HEADER_BYTES;
730 push(@magic_tests, "(\n$check\n)");
733 $! = 2, die "$file $ln: unknown command\n";
740 if (!$STDERR_IS_TTY) {
741 print STDERR $_[0], "\n";
744 $thislength = length($text);
745 if ($thislength >= $last_message_length) {
746 print STDERR $text, "\r";
748 print STDERR $text, ' 'x ($last_message_length-$thislength),"\r";
750 $last_message_length = $thislength;
756 print STDERR ' ' x $last_message_length, "\r" if $last_message_length;
757 $vv_print = $vv_size = $last_message_length = 0;
761 ## Output a copy of this program with comments, extra whitespace, and
762 ## the trailing man page removed. On an ultra slow machine, such a copy
763 ## might load faster (but I can't tell any difference on my machine).
766 seek(DATA, 0, 0) || die "$0: can't reset internal pointer.\n";
768 print, next if /INLINE_LITERAL_TEXT/.../INLINE_LITERAL_TEXT/;
769 ## must mention INLINE_LITERAL_TEXT on this line!
770 s/\#\#.*|^\s+|\s+$//; ## remove cruft
771 last if $_ eq '.00;';
772 next if ($_ eq '') || ($_ eq "'di'") || ($_ eq "'ig00'");
773 s/\$stripped=0;/\$stripped=1;/;
774 s/\s\s+/ /; ## squish multiple whitespaces down to one.
781 ## Just to shut up -w. Never executed.
785 1 || &dummy || &dir_done || &bad || &message || $NEXT_DIR_ENTRY ||
786 $DELAY || $VV_SIZE || $VV_PRINT_COUNT || $STDERR_SCREWS_STDOUT ||
787 @files || @files || $magic'H || $magic'H || $xdev{''} || &clear_message;
792 ## If the following __END__ is in place, what follows will be
793 ## inlined when the program first starts up. Any $ variable name
794 ## all in upper case, specifically, any string matching
795 ## \$([A-Z][A-Z0-9_]{2,}\b
796 ## will have the true value for that variable inlined. Also, any 'eval' is
799 ## The idea is that when the whole thing is then eval'ed to define &dodir,
800 ## the perl optimizer will make all the decisions that are based upon
801 ## command-line options (such as $VERBOSE), since they'll be inlined as
804 ## Also, and here's the big win, the tests for matching the regex, and a
805 ## few others, are all inlined. Should be blinding speed here.
807 ## See the read from <DATA> above for where all this takes place.
808 ## But all-in-all, you *want* the __END__ here. Comment it out only for
815 ## Given a directory, check all "appropriate" files in it.
816 ## Shove any subdirectories into the global @todo, so they'll be done
819 ## Be careful about adding any upper-case variables, as they are subject
820 ## to being inlined. See comments above the __END__ above.
825 $dir =~ s,/+$,,; ## remove any trailing slash.
826 unless (opendir(DIR, "$dir/.")) {
827 &clear_message if $VERBOSE && $STDERR_SCREWS_STDOUT;
828 warn qq($0: can't opendir "$dir/".\n);
834 $vv_print = $vv_size = 0;
837 @files = sort readdir(DIR) if $DO_SORT;
839 while (defined($name = eval $NEXT_DIR_ENTRY))
841 next if $name eq '.' || $name eq '..'; ## never follow these.
843 ## create full relative pathname.
844 $file = $dir eq '.' ? $name : "$dir/$name";
846 ## if link and skipping them, do so.
847 if ($NOLINKS && -l $file) {
848 warn qq/skip (symlink): $file\n/ if $WHY;
852 ## skip things unless files or directories
853 unless (-f $file || -d _) {
855 $why = (-S _ && "socket") ||
857 (-b _ && "block special")||
858 (-c _ && "char special") || "somekinda special";
859 warn qq/skip ($why): $file\n/;
864 ## skip things we can't read
867 $why = (-l $file) ? "follow" : "read";
868 warn qq/skip (can't $why): $file\n/;
873 ## skip things that are empty
874 unless (-s _ || -d _) {
875 warn qq/skip (empty): $file\n/ if $WHY;
879 ## Note file device & inode. If -xdev, skip if appropriate.
880 ($dev, $inode) = (stat(_))[$STAT_DEV, $STAT_INODE];
881 if ($XDEV && defined $xdev{$dev}) {
882 warn qq/skip (other device): $file\n/ if $WHY;
887 ## special work for a directory
889 ## Do checks for directory file endings.
890 if ($DO_DSKIP_TEST && (eval $DSKIP_TEST)) {
891 warn qq/skip (-dskip): $file\n/ if $WHY;
894 ## do checks for -name/-regex/-path tests
895 if ($DO_DGLOB_TESTS && !(eval $DGLOB_TESTS)) {
896 warn qq/skip (dirname): $file\n/ if $WHY;
900 ## _never_ redo a directory
901 if (defined $dir_done{$id} and $^O ne 'MSWin32') {
902 warn qq/skip (did as "$dir_done{$id}"): $file\n/ if $WHY;
905 $dir_done{$id} = $file; ## mark it done.
906 unshift(@todo, $file); ## add to the list to do.
909 if ($WHY == 0 && $VERBOSE > 1) {
910 if ($VERBOSE>2||$vv_print++>$VV_PRINT_COUNT||($vv_size+=-s _)>$VV_SIZE){
912 $vv_print = $vv_size = 0;
916 ## do time-related tests
917 if ($NEWER || $OLDER) {
918 $_ = (stat(_))[$STAT_MTIME];
919 if ($NEWER && $_ < $NEWER) {
920 warn qq/skip (too old): $file\n/ if $WHY;
923 if ($OLDER && $_ > $OLDER) {
924 warn qq/skip (too new): $file\n/ if $WHY;
929 ## do checks for file endings
930 if ($DO_SKIP_TEST && (eval $SKIP_TEST)) {
931 warn qq/skip (-skip): $file\n/ if $WHY;
935 ## do checks for -name/-regex/-path tests
936 if ($DO_GLOB_TESTS && !(eval $GLOB_TESTS)) {
937 warn qq/skip (filename): $file\n/ if $WHY;
942 ## If we're not repeating files,
943 ## skip this one if we've done it, or note we're doing it.
945 if (defined $file_done{$id}) {
946 warn qq/skip (did as "$file_done{$id}"): $file\n/ if $WHY;
949 $file_done{$id} = $file;
952 if ($DO_MAGIC_TESTS) {
953 if (!open(FILE_IN, $file)) {
954 &clear_message if $VERBOSE && $STDERR_SCREWS_STDOUT;
955 warn qq/$0: can't open: $file\n/;
958 unless (read(FILE_IN, $magic'H, $HEADER_BYTES)) {
959 &clear_message if $VERBOSE && $STDERR_SCREWS_STDOUT;
960 warn qq/$0: can't read from "$file"\n"/;
968 warn qq/skip (magic): $file\n/ if $WHY;
971 seek(FILE_IN, 0, 0); ## reset for later <FILE_IN>
974 if ($WHY != 0 && $VERBOSE > 1) {
975 if ($VERBOSE>2||$vv_print++>$VV_PRINT_COUNT||($vv_size+=-s _)>$VV_SIZE){
977 $vv_print = $vv_size = 0;
986 &clear_message if $VERBOSE && $STDERR_SCREWS_STDOUT;
988 $retval=0; ## we've found something
989 close(FILE_IN) if $DO_MAGIC_TESTS;
992 ## if we weren't doing magic tests, file won't be open yet...
993 if (!$DO_MAGIC_TESTS && !open(FILE_IN, $file)) {
994 &clear_message if $VERBOSE && $STDERR_SCREWS_STDOUT;
995 warn qq/$0: can't open: $file\n/;
998 if ($LIST_ONLY && $CAN_USE_FAST_LISTONLY) {
1000 ## This is rather complex, but buys us a LOT when we're just
1001 ## listing files and not the individual internal lines.
1003 local($size) = 4096; ## block-size in which to do reads
1004 local($nl); ## will point to $_'s ending newline.
1005 local($read); ## will be how many bytes read.
1006 local($_) = ''; ## Starts out empty
1007 local($hold); ## (see below)
1009 while (($read = read(FILE_IN,$_,$size,length($_)))||length($_))
1012 ## if read a full block, but no newline, need to read more.
1013 while ($read == $size && ($nl = rindex($_, "\n")) < 0) {
1014 push(@parts, $_); ## save that part
1015 $read = read(FILE_IN, $_, $size); ## keep trying
1019 ## If we had to save parts, must now combine them together.
1020 ## adjusting $nl to reflect the now-larger $_. This should
1021 ## be a lot more efficient than using any kind of .= in the
1025 local($lastlen) = length($_); #only need if $nl >= 0
1026 $_ = join('', @parts, $_);
1027 $nl = length($_) - ($lastlen - $nl) if $nl >= 0;
1031 ## If we're at the end of the file, then we can use $_ as
1032 ## is. Otherwise, we need to remove the final partial-line
1033 ## and save it so that it'll be at the beginning of the
1034 ## next read (where the rest of the line will be layed in
1035 ## right after it). $hold will be what we should save
1038 if ($read != $size || $nl < 0) {
1041 $hold = substr($_, $nl + 1);
1042 substr($_, $nl + 1) = '';
1046 ## Now have a bunch of full lines in $_. Use it.
1048 if (eval $REGEX_TEST) {
1049 &clear_message if $VERBOSE && $STDERR_SCREWS_STDOUT;
1051 $retval=0; ## we've found something
1056 ## Prepare for next read....
1060 } else { ## else not using faster block scanning.....
1062 $lines_printed = 0 if $NICE;
1065 next unless (eval $REGEX_TEST);
1068 ## We found a matching line.
1071 &clear_message if $VERBOSE && $STDERR_SCREWS_STDOUT;
1076 ## prepare to print line.
1077 if ($NICE && $lines_printed++ == 0) {
1078 print '-' x 70, "\n" if $NICE > 1;
1083 ## Print all the prelim stuff. This looks less efficient
1084 ## than it needs to be, but that's so that when the eval
1085 ## is compiled (and the tests are optimized away), the
1086 ## result will be less actual PRINTs than the more natural
1087 ## way of doing these tests....
1090 if ($REPORT_LINENUM) {
1095 } elsif ($REPORT_LINENUM && $PREPEND_FILENAME) {
1096 print "$file,:$.: ";
1097 } elsif ($PREPEND_FILENAME) {
1099 } elsif ($REPORT_LINENUM) {
1103 print "\n" unless m/\n$/;
1106 print "\n" if ($NICE > 1) && $lines_printed;
1117 'di \" finish diversion--previous line must be blank
1118 .nr nl 0-1 \" fake up transition to first page again
1119 .nr % 0 \" start at page 1
1120 .\"__________________NORMAL_MAN_PAGE_BELOW_________________
1122 .TH search 1 "Dec 17, 1994"
1124 search \- search files (a'la grep) in a whole directory tree.
1126 search [ grep-like and find-like options] [regex ....]
1129 is more or less a combo of 'find' and 'grep' (although the regular
1130 expression flavor is that of the perl being used, which is closer to
1131 egrep's than grep's).
1134 does generally the same kind of thing that
1136 find <blah blah> | xargs egrep <blah blah>
1140 more powerful and efficient (and intuitive, I think).
1142 This manual describes
1144 as of version "941227.4".
1147 Basic use is simple:
1151 will search files in the current directory, and all sub directories, for
1152 files that have "jeff" in them. The lines will be listed with the
1153 containing file's name prepended.
1155 If you list more than one regex, such as with
1157 % search jeff Larry Randal+ 'Stoc?k' 'C.*son'
1159 then a line containing any of the regexes will be listed.
1160 This makes it effectively the same as
1162 % search 'jeff|Larry|Randal+|Stoc?k|C.*son'
1164 However, listing them separately is much more efficient (and is easier
1167 Note that in the case of these examples, the
1169 (list whole-words only) option would be useful.
1171 Normally, various kinds of files are automatically removed from consideration.
1172 If it has has a certain ending (such as ".tar", ".Z", ".o", .etc), or if
1173 the beginning of the file looks like a binary, it'll be excluded.
1174 You can control exactly how this works -- see below. One quick way to
1175 override this is to use the
1177 option, which means to consider all the files that would normally be
1178 automatically excluded.
1179 Or, if you're curious, you can use
1181 to have notes about what files are skipped (and why) printed to stderr.
1183 .SH "BASIC OVERVIEW"
1184 Normally, the search starts in the current directory, considering files in
1189 file to control ways to automatically exclude files.
1190 If you don't have this file, a default one will kick in, which automatically
1195 (among others) to exclude those kinds of files (which you probably want to
1196 skip when searching for text, as is normal).
1197 Files that look to be be binary will also be excluded.
1199 Files ending with "#" and "~" will also be excluded unless the
1205 to show what kinds of files will normally be skipped.
1206 See the section on the startup file
1211 option to indicate you want to consider all files that would otherwise be
1212 skipped by the startup file.
1214 Based upon various other flags (see "WHICH FILES TO CONSIDER" below),
1215 more files might be removed from consideration. For example
1219 will exclude files that aren't at least three days old (change the 3 to -3
1220 to exclude files that are more than three days old), while
1224 would exclude any file beginning with a dot (of course, '.' and '..' are
1225 special and always excluded).
1227 If you'd like to see what files are being excluded, and why, you can get the
1232 If a file makes it past all the checks, it is then "considered".
1233 This usually means it is greped for the regular expressions you gave
1234 on the command line.
1236 If any of the regexes match a line, the line is printed.
1239 is given, just the filename is printed. Or, if
1241 is given, a somewhat more (human-)readable output is generated.
1243 If you're searching a huge tree and want to keep informed about how
1244 the search is progressing,
1246 will print (to stderr) the current directory being searched.
1249 will also print the current file "every so often", which could be useful
1250 if a directory is huge. Using
1252 will print the update with every file.
1254 Below is the full listing of options.
1256 .SH "OPTIONS TELLING *WHERE* TO SEARCH"
1259 Start searching at the named directory instead of the current directory.
1262 arguments are given, multiple trees will be searched.
1267 except it flushes any previous
1269 directories (i.e. "-dir A -dir B -dir C" will search A, B, and C, while
1270 "-dir A -ddir B -dir C" will search only B and C. This might be of use
1271 in the startup file (see that section below).
1274 Stay on the same filesystem as the starting directory/directories.
1277 Sort the items in a directory before processing them.
1278 Normally they are processed in whatever order they happen to be read from
1282 Don't follow symbolic links. Normally they're followed.
1284 .SH "OPTIONS CONTROLLING WHICH FILES TO CONSIDER AND EXCLUDE"
1287 Only consider files that were last changed more than
1294 has '-' prepended, i.e. "-mtime -2.5" means to consider files that
1295 have been changed in the last two and a half days).
1298 Only consider files that have not changed since
1301 If there is any upper case in the "-older", "or equal" is added to the sense
1302 of the test. Therefore, "search -older ./file regex" will never consider
1303 "./file", while "search -Older ./file regex" will.
1305 If a file is a symbolic link, the time used is that of the file and not the
1313 Only consider files that match the shell filename pattern
1315 The check is only done on a file's name (use
1317 to check the whole path, and use
1319 to check directory names).
1321 Multiple specifications can be given by separating them with spaces, a'la
1325 to consider C source and header files.
1328 doesn't contain any special pattern characters, a '*' is prepended.
1329 This last example could have been given as
1333 It could also be given as
1339 -name '*.c' -name '*.h'
1346 but in this last case, you have to be sure to supply the leading '*'.
1351 except the entire path is checked against the pattern.
1354 Considers files whose names (not paths) match the given perl regex
1358 Case-insensitive version of
1362 Case-insensitive version of
1365 .BI -iregex " REGEX"
1366 Case-insensitive version of
1371 Only search down directories whose path matches the given pattern (this
1372 doesn't apply to the initial directory given by
1377 -dir /usr/man -dpath /usr/man/man*
1379 would completely skip
1380 "/usr/man/cat1", "/usr/man/cat2", etc.
1383 Skips directories whose name (not path) matches the given pattern.
1386 -dir /usr/man -dskip cat*
1388 would completely skip any directory in the tree whose name begins with "cat"
1389 (including "/usr/man/cat1", "/usr/man/cat2", etc.).
1391 .BI -dregex " REGEX"
1394 but the pattern is a full perl regex. Note that this quite different
1397 which considers only file names (not paths). This option considers
1398 full directory paths (not just names). It's much more useful this way.
1399 Sorry if it's confusing.
1402 This option exists, but is probably not very useful. It probably wants to
1403 be like the '-below' or something I mention in the "TODO" section.
1406 Case-insensitive version of
1410 Case-insensitive version of
1413 .BI -idregex " REGEX"
1414 Case-insensitive version of
1418 Ignore any 'magic' or 'option' lines in the startup file.
1419 The effect is that all files that would otherwise be automatically
1420 excluded are considered.
1423 Arguments starting with
1427 explained elsewhere) do special interaction with the
1429 startup file. Something like
1433 will turn on "flag1" and "flag2" in the startup file (and is
1434 the same as "-xflag1,flag2"). You can use this to write your own
1435 rules for what kinds of files are to be considered.
1437 For example, the internal-default startup file contains the line
1439 <!~> option: -skip '~ #'
1441 This means that if the
1450 The effect is that emacs temp and backup files are not normally
1451 considered, but you can included them with the -x~ flag.
1453 You can write your own rules to customize
1455 in powerful ways. See the STARTUP FILE section below.
1458 Print a message (to stderr) when and why a file is not considered.
1460 .SH "OPTIONS TELLING WHAT TO DO WITH FILES THAT WILL BE CONSIDERED"
1466 This option changes the basic action of
1469 Normally, if a file is considered, it is searched
1470 for the regular expressions as described earlier. However, if this option
1471 is given, the filename is printed and no searching takes place. This turns
1473 into a 'find' of some sorts.
1475 In this case, no regular expressions are needed on the command line
1476 (any that are there are silently ignored).
1478 This is not intended to be a replacement for the 'find' program,
1480 you in understanding just what files are getting past the exclusion checks.
1481 If you really want to use it as a sort of replacement for the 'find' program,
1482 you might want to use
1484 so that it doesn't waste time checking to see if the file is binary, etc
1485 (unless you really want that, of course).
1489 none of the "GREP-LIKE OPTIONS" (below) matter.
1491 As a replacement for 'find',
1493 is probably a bit slower (or in the case of GNU find, a lot slower --
1497 However, "search -ffind"
1498 might be more useful than 'find' when options such as
1500 are used (at least until 'find' gets such functionality).
1505 A faster more 'find'-like find. Does
1509 .SH "GREP-LIKE OPTIONS"
1510 These options control how a searched file is accessed,
1511 and how things are printed.
1514 Ignore letter case when matching.
1517 Consider only whole-word matches ("whole word" as defined by perl's "\\b"
1521 If the regex(es) is/are simple, try to modify them so that they'll work
1522 in manpage-like underlined text (i.e. like _^Ht_^Hh_^Hi_^Hs).
1523 This is very rudimentary at the moment.
1529 Don't print matching lines, but the names of files that contain matching
1530 lines. This will likely be *much* faster, as special optimizations are
1531 made -- particularly with large files.
1534 Pepfix each line by its line number.
1537 Not a grep-like option, but similar to
1541 will have the output be a bit more human-readable, with matching lines printed
1542 slightly indented after the filename, a'la
1546 somedir/somefile: line with foo in it
1547 somedir/somefile: some food for thought
1548 anotherdir/x: don't be a buffoon!
1558 some food for thought
1564 This option due to Lionel Cons.
1569 Prefix each file's output by a rule line, and follow with an extra blank line.
1572 Don't prepend each output line with the name of the file
1582 Print the usage information.
1585 Print the version information and quit.
1588 Set the level of message verbosity.
1590 will print a note whenever a new directory is entered.
1592 will also print a note "every so often". This can be useful to see
1593 what's happening when searching huge directories.
1595 will print a new with every file.
1603 This ends the options, and can be useful if the regex begins with '-'.
1606 Shows what is being considered in the startup file, then exits.
1609 Normally, an identical file won't be checked twice (even with multiple
1610 hard or symbolic links). If you're just trying to do a fast
1612 the bookkeeping to remember which files have been seen is not desirable,
1613 so you can eliminate the bookkeeping with this flag.
1618 starts up, it processes the directives in
1620 If no such file exists, a default
1621 internal version is used.
1623 The internal version looks like:
1626 magic: 32 : $H =~ m/[\ex00-\ex06\ex10-\ex1a\ex1c-\ex1f\ex80\exff]{2}/
1627 option: -skip '.a .COM .elc .EXE .gz .o .pbm .xbm .dvi'
1628 option: -iskip '.tarz .zip .z .lzh .jpg .jpeg .gif .uu'
1629 <!~> option: -skip '~ #'
1632 If you wish to create your own "~/.search",
1633 you might consider copying the above, and then working from there.
1635 There are two kinds of directives in a startup file: "magic" and "option".
1639 Option lines will automatically do the command-line options given.
1640 For example, the line
1644 in you startup file will turn on -v every time, without needing to type it
1645 on the command line.
1647 The text on the line after the "option:" directive is processed
1648 like the Bourne shell, so make sure to pay attention to quoting.
1650 option: -skip .exe .com
1652 will give an error (".com" by itself isn't a valid option), while
1654 option: -skip ".exe .com"
1656 will properly include it as part of -skip's argument.
1660 Magic lines are used to determine if a file should be considered a binary
1661 or not (the term "magic" refers to checking a file's magic number). These
1662 are described in more detail below.
1665 Blank lines and comments (lines beginning with '#') are allowed.
1667 If a line begins with <...>, then it's a check to see if the
1668 directive on the line should be done or not. The stuff inside the <...>
1669 can contain perl's && (and), || (or), ! (not), and parens for grouping,
1670 along with "flags" that might be indicated by the user with
1674 For example, using "-xfoo" will cause "foo" to be true inside the <...>
1675 blocks. Therefore, a line beginning with "<foo>" would be done only when
1676 "-xfoo" had been specified, while a line beginning with "<!foo>" would be
1677 done only when "-xfoo" is not specified (of course, a line without any <...>
1678 is done in either case).
1680 A realistic example might be
1684 This will cause -vv messages to be the default, but allow "-xv" to override.
1686 There are a few flags that are set automatically:
1690 true if the output is to the screen (as opposed to being redirected to a file).
1691 You can force this (as with all the other automatic flags) with -xTTY.
1694 True if -v was specified. If -vv was specified, both
1698 flags are true (and so on).
1701 True if -nice was specified. Same thing about -nnice as for -vv.
1705 true if -list (or -l) was given.
1708 true if -dir was given.
1711 Using this info, you might change the last example to
1714 <!v && !-v> option: -vv
1717 The added "&& !-v" means "and if the '-v' option not given".
1718 This will allow you to use "-v" alone on the command line, and not
1719 have this directive add the more verbose "-vv" automatically.
1722 Some other examples:
1724 <!-dir && !here> option: -dir ~/
1725 Effectively make the default directory your home directory (instead of the
1726 current directory). Using -dir or -xhere will undo this.
1728 <tex> option: -name .tex -dir ~/pub
1729 Create '-xtex' to search only "*.tex" files in your ~/pub directory tree.
1730 Actually, this could be made a bit better. If you combine '-xtex' and '-dir'
1731 on the command line, this directive will add ~/pub to the list, when you
1732 probably want to use the -dir directory only. You could do
1735 <tex> option: -name .tex
1736 <tex && !-dir> option: -dir ~/pub
1739 to will allow '-xtex' to work as before, but allow a command-line "-dir"
1740 to take precedence with respect to ~/pub.
1742 <fluff> option: -nnice -sort -i -vvv
1743 Combine a few user-friendly options into one '-xfluff' option.
1745 <man> option: -ddir /usr/man -v -w
1746 When the '-xman' option is given, search "/usr/man" for whole-words
1747 (of whatever regex or regexes are given on the command line), with -v.
1750 The lines in the startup file are executed from top to bottom, so something
1754 <both> option: -xflag1 -xflag2
1755 <flag1> option: ...whatever...
1756 <flag2> option: ...whatever...
1759 will allow '-xboth' to be the same as '-xflag1 -xflag2' (or '-xflag1,flag2'
1760 for that matter). However, if you put the "<both>" line below the others,
1761 they will not be true when encountered, so the result would be different
1762 (and probably undesired).
1764 The "magic" directives are used to determine if a file looks to be binary
1765 or not. The form of a magic line is
1767 magic: \fISIZE\fP : \fIPERLCODE\fP
1771 is the number of bytes of the file you need to check, and
1773 is the code to do the check. Within
1775 the variable $H will hold at least the first
1777 bytes of the file (unless the file is shorter than that, of course).
1778 It might hold more bytes. The perl should evaluate to true if the file
1779 should be considered a binary.
1783 magic: 6 : substr($H, 0, 6) eq 'GIF87a'
1785 to test for a GIF ("-iskip .gif" is better, but this might be useful
1786 if you have images in files without the ".gif" extension).
1788 Since the startup file is checked from top to bottom, you can be a bit
1791 magic: 6 : ($x6 = substr($H, 0, 6)) eq 'GIF87a'
1792 magic: 6 : $x6 eq 'GIF89a'
1794 You could also write the same thing as
1796 magic: 6 : (($x6 = substr($H, 0, 6)) eq 'GIF87a') || ## an old gif, or.. \e
1797 $x6 eq 'GIF89a' ## .. a new one.
1799 since newlines may be escaped.
1801 The default internal startup file includes
1803 magic: 32 : $H =~ m/[\ex00-\ex06\ex10-\ex1a\ex1c-\ex1f\ex80\exff]{2}/
1805 which checks for certain non-printable characters, and catches a large
1806 number of binary files, including most system's executables, linkable
1807 objects, compressed, tarred, and otherwise folded, spindled, and mutilated
1810 Another example might be
1812 ## an archive library
1813 magic: 17 : substr($H, 0, 17) eq "!<arch>\en__.SYMDEF"
1818 returns zero if lines (or files, if appropriate) were found,
1819 or if no work was requested (such as with
1821 Returns 1 if no lines (or files) were found.
1825 Things I'd like to add some day:
1827 + show surrounding lines (context).
1828 + highlight matched portions of lines.
1829 + add '-and', which can go between regexes to override
1830 the default logical or of the regexes.
1831 + add something like
1833 which will examine a tree and only consider files that
1834 lie in a directory deeper than one named by the pattern.
1835 + add 'warning' and 'error' directives.
1836 + add 'help' directive.
1839 If -xdev and multiple -dir arguments are given, any file in any of the
1840 target filesystems are allowed. It would be better to allow each filesystem
1841 for each separate tree.
1843 Multiple -dir args might also cause some confusing effects. Doing
1845 -dir some/dir -dir other
1847 will search "some/dir" completely, then search "other" completely. This
1848 is good. However, something like
1850 -dir some/dir -dir some/dir/more/specific
1852 will search "some/dir" completely *except for* "some/dir/more/specific",
1853 after which it will return and be searched. Not really a bug, but just sort
1856 File times (for -newer, etc.) of symbolic links are for the file, not the
1857 link. This could cause some misunderstandings.
1859 Probably more. Please let me know.
1861 Jeffrey Friedl, Omron Corp (jfriedl@omron.co.jp)
1863 http://www.wg.omron.co.jp/cgi-bin/j-e/jfriedl.html
1866 See http://www.wg.omron.co.jp/~jfriedl/perl/index.html