#!/bin/sh -- # A comment mentioning perl, to prevent perl from looping. Indented to work with bash. eval 'exec perl -S $0 ${1+"$@"}' if 0; #!/usr/local/bin/perl chop($program = `basename $0`); $debug_during = ''; $debug = ''; $print_filename = 'T'; $print_filename_only = ''; $file_pattern = ''; $path_pattern = ''; $quote = ''; $binary = ''; $dir='.'; $cmd='egrep'; $Usage=<<"EOU"; $program: Recurse down directory tree and $cmd ordinary files for patterns. It is essentially a marriage of the "find" and "$cmd" commands with (presumably) a less awkward syntax. Usage: $program [<${program}_opts>] [--] [<${cmd}_opts>] where <${program}_opts> can be: -help this help. -debug -D no action, just print command line parse. -d find files starting in instead of "$dir" put a list of dir's space separated inside quotes. -cmd use instead of "$cmd". -file only do file basenames matching perl regexp -path as -file, but apply regexp to full path. -q1 quote all the non - starting <${cmd}_opts> with: ' -q2 quote all the non - starting <${cmd}_opts> with: " -q same as -q1. -h do not print filenames in output. -H ONLY print filenames in output. -b,-bin search non-text files as well. Use "--" to signal end of <${program}_opts>, if not present you are allowed at most one ${program}_opt. Examples: $program #include Find all "#include" lines in this directory and all sub-directories. (non binary files). $program -h -q -- -i 'foo.*(bar)' Do not print out filenames. Quote the nasty regexp. Pass -i flag to $cmd EOU $debug = 'True' if $program =~ /^Rg/; select STDERR; $| = 1; select STDOUT; $| = 1; @ARGV_orig = @ARGV; $one_opt_only = 'True'; foreach $arg (@ARGV) { if ( $arg eq '--' || $arg eq ',' ) { $one_opt_only = ''; last; } } if ( $ARGV[0] eq '-h' && $ARGV[1] eq '' ) { &help; exit 0; } $count = '0'; LOOP: # process command line arguments... while (@ARGV) { if($count++ > 0 && $one_opt_only ) { last LOOP; } $_ = shift; $got_opt = ''; CASE: { /^--$/ && (last LOOP); /^\,$/ && (last LOOP); /^-help/ && ( (&help), exit 0, last CASE); /^-debug$|^-D$/ && ( $debug = 'T', $got_opt = 'T', last CASE); /^-d$/ && ( $dir = shift, $got_opt = 'T', last CASE); /^-h$/ && ( $print_filename = '', $got_opt = 'T', last CASE); /^-H$/ && ( $print_filename_only = 'T', $got_opt = 'T', last CASE); /^-file$/ && ( $file_pattern = shift, $got_opt = 'T', last CASE); /^-path$/ && ( $path_pattern = shift, $got_opt = 'T', last CASE); /^-q$/ && ( $quote = '1', $got_opt = 'T', last CASE); /^-b/ && ( $binary = 'T', $got_opt = 'T', last CASE); /^-q1$/ && ( $quote = '1', $got_opt = 'T', last CASE); /^-q2$/ && ( $quote = '2', $got_opt = 'T', last CASE); /^-cmd$/ && ( $cmd = shift, $got_opt = 'T', last CASE); /^--$/ && (last LOOP); # -- means end of switches /^-(-.*)$/ && (unshift(@ARGV, $1), last CASE); if ( /^-(..+)$/ ) { # split bundled switches: local($y, $x) = ($1, ''); foreach $x (reverse(split(//, $y))) { unshift(@ARGV,"-$x") }; last CASE; } } if ( $one_opt_only && ! $got_opt ) { unshift(@ARGV,$_); # must be grep opt. } } #if ($file_pattern) { # $file_pattern =~ s/(\W)/\\$1/g; #} if ($quote) { foreach $arg (@ARGV) { if ( $arg !~ '^-' ) { $arg = '\''.$arg.'\'' if $quote eq '1'; $arg = '"'.$arg.'"' if $quote eq '2'; } } } $cmd_args = join(' ', @ARGV); if ( $debug ) { print "debug is: $debug\n"; print "dir is: $dir\n"; print "print_filename: $print_filename\n"; print "file_pattern is: $file_pattern\n"; print "path_pattern is: $path_pattern\n"; print "quote is: $quote\n"; print "binary is: $binary\n"; print "cmd is: $cmd\n"; print "$cmd args is: $cmd_args\n"; exit 0; } open(FILES, "find $dir -type f -print|"); while () { chop($_); print STDOUT "db:$_\n" if $debug_during; $result = ''; next if $path_pattern ne '' && $_ !~ /$path_pattern/; if ( $file_pattern ne '' ) { chop($basename = `basename $_`); next if $basename !~ /$file_pattern/; } next if !$binary && ! -T $_; next if -p "$_"; # how come named pipes don't always work?? # $pipe_test = ''; # chop($pipe_test = `sh -c \"if [ -p $_ ]; then echo T; fi\"`); # next if $pipe_test eq 'T'; if ( -T "$_" ) { # chop( $result = `$cmd @ARGV $_`); $file = $_; $file =~ s/\"/\\\"/g; chop( $result = `$cmd $cmd_args "$file"`); } if ( $result ne '' ) { if ( $print_filename_only ) { print STDOUT "$_\n"; } elsif ( $print_filename ) { $result =~ s/\n/\n$_:/g; print STDOUT "$_:$result\n"; } else { print STDOUT "$result\n"; } } } close(FILES); exit 0; #sub help { # print STDOUT $Usage; #} sub help { if ( open(MORE, "|more") ) { # open pipeline to "more" print MORE "$Usage"; close(MORE); } else { print STDERR "$Usage"; } }