[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

[MacPerl] Generic Search Script 2.2




Some additional fixes for the Search script I recently posted.

Ero Brown



#========================================================================
#========================================================================
#
# Search.pl
#
# Author: Ero Brown <ero@fiber.net>
#
# Version: 2.2
#
# Special thanks to Paul J. Schinder, Chris Nandor, and
# Ronald J. Kimball who's suggestions helped make this a much better
# script.  Also, thanks to Raffael Cavallaro, RenŽ Laterveer,
# Jay Bedsole, Richard Gordon, and Thomas R. Kimtpon for their
# helpful comments.  Changes from the original are too numerous
# to list!
#
#========================================================================
#========================================================================

#!/usr/local/bin/perl

### required modules needed for this script
use File::Find;
use File::Basename;
use Getopt::Long;


#========================================================================

### Forward declare all sub-routines used
sub Usage;
sub ReadArguments;
sub DoAFile;
sub SearchFilter;


#========================================================================
# Function: Usage
# Purpose:  this details the usage of this script -- we can call this
#           function when a invalid usage error occurs.
#========================================================================
sub Usage {
   die <<END_USAGE;
usage: $0 [-r] [-c] [-i] [-s] [-m] [-p]
               [-f <expression>] -e <expression> <folder(s) &| file(s) . . .>
   -r   recursively process encountered sub-directories
   -c   only list a total count of matching occurrances
   -i   make pattern matching case insensitive
   -s   print summary information only
   -m   mpw style output
   -p   print progress and summary information
   -f   file expression representing a file filter
   -e   the expression representing what you are searching for

   *Parameters can be given in any order.

   *Fully resolved pathnames are required, partial pathnames will
    cause this script to barf.

   Version 2.2
END_USAGE
}


#========================================================================
# Function: ReadArguments
# Purpose:  Parse the arguments array and set the appropriate flags.
#========================================================================
sub ReadArguments
{
   #if no arguments are passed in, assume the user needs some help
   if (@ARGV < 1) {
      Usage;
   }

   $res = Getopt::Long::GetOptions("r", "c", "i", "s", "m", "p",
                           "f=s" => \$fileFilter,
                           "e=s" => \$expression);
   if (!$res) {
      Usage;
   }

   $recurseOpt = $opt_r;
   $countOnlyOpt = $opt_c;
   $caseInSensitive = $opt_i;
   $summaryInfoOnly = $opt_s;
   $mpwOutputOpt = $opt_m;
   $progressOpt = $opt_p;
   $fileFilterOpt = $fileFilter ne '';
   $expressionOpt = $expression ne '';

   $pad = "";
   if ($progressOpt) {
      $pad = "\t";
   }
   $lst = "";
   if ($mpwOutputOpt) {
      $lst = "# ";
   }

   #if no directories/files are passed in, assume the user needs some help
   if (@ARGV < 1) {
      print "# At least one directory or file to search must be specified.\n";
      Usage;
   }
   if (!$expressionOpt) {
      print "# The required -e expression option was NOT specified.\n";
      Usage;
   }
}


#========================================================================
# Function: DoAFile
# Purpose:  process the file/directory
#           this is where the action is -- look at every file and
#           directory and perform the desired operations.
#========================================================================
sub DoAFile {
   my ($theFile) = @_;
   my ($shortName, $tempFName, $doSearch, $found, $lineCount, $tFoundCount);

   if (-f $theFile) {
      $fileCount++;
      if ($progressOpt) {
         print $pad, $lst, "FILE: $theFile\n";
      }
      $shortName = File::Basename::basename($theFile);
      if ($summaryInfoOnly) {
         $tempFName = $theFile;
      }
      else {
         $tempFName = $shortName;
      }

      $doSearch = 1;
      if ($fileFilterOpt) {
         $doSearch = 0;
         if ($caseInSensitive) {
            if (eval($shortName =~ /$fileFilter/oi)) {
               $doSearch = 1;
            }
         }
         else {
            if (eval($shortName =~ /$fileFilter/o)) {
               $doSearch = 1;
            }
         }
      }

      if ($doSearch) {
         $tFoundCount = 0;
         $lineCount = 1;
         if ($progressOpt) {
            print $pad, $pad, $lst, "Searching $shortName...\n";
         }

         if (open(THEFILE, "< $theFile\0")) {
            while ($lineStr= <THEFILE>) {
               $found = 0;
               if ($caseInSensitive) {
                  if (eval($lineStr =~ /$expression/oi)) {
                     $found = 1;
                  }
               }
               else {
                  if (eval($lineStr =~ /$expression/o)) {
                     $found = 1;
                  }
               }
               if ($found) {
                  $tFoundCount++;
                  if (!$countOnlyOpt && !$summaryInfoOnly) {
                     if (length($lineStr) > 255) {
                        $lineStr =  "### LINE TOO LONG TO PRINT ###\n";
                     }
                     if ($mpwOutputOpt) {
                        print $pad, $pad, "File \"", $theFile, "\"; ";
                        print "Line ", $lineCount, ":¤ \t# ", $lineStr;
                     }
                     else {
                        print $pad, $pad, $theFile, " -- line #";
                        print $lineCount, "\n", $pad, $pad, $pad, $lineStr;
                     }
                  }
               }
               $lineCount++;
            }
            close(THEFILE);
            if (($progressOpt || $summaryInfoOnly) && ($tFoundCount > 0)) {
               if ($mpwOutputOpt && $summaryInfoOnly) {
                  print $pad, $pad, "OPEN \"", $theFile, "\" \t# -- ";
                  print $tFoundCount, " occurrances of the search ";
                  print "expression.\n";
               }
               else
               {
                  print $pad, $pad, $lst, $tempFName, " -- had ", $tFoundCount;
                  print " occurrances of the search expression.\n";
               }
            }
            $foundCount += $tFoundCount;
         }
         else {
            $errorCount++;
            if ($progressOpt || $summaryInfoOnly) {
               print $pad, $pad, "# ERROR! couldn't open: \"$tempFName\";
               print " -- $!\n";
            }
         }
      }

   }
   # it must be a directory (-d $theFile)
   else {
      $dirCount++;
      if ($progressOpt) {
         print $lst, "DIRECTORY: $theFile\n";
      }
   }
}


#========================================================================
# Function: SearchFilter
# Purpose:  We need to provide this function for the File::Find::find()
#           function in the File::Find module -- this is so we can control
#           (via filter) what kind of files and/or directories get handled.
#========================================================================
sub SearchFilter
{
   #filter so we only process the files/directories we want
   (
      ( -e $_ && -s $_ ) &&
      (
         ( -f $_ && -r $_ && -T $_ ) ||
         ( -d $_ && -x $_ &&
         ( $recurseOpt || ( !$recurseOpt && ($File::Find::prune = 1) ) ) )
      )
   ) &&
   DoAFile($File::Find::name);  #call our function that does the checking
}


#========================================================================
#============================   MAIN   ==================================
#========================================================================

### main part of the program --
### we go through every file and directory passed in on
### the command line and check it for validity.

#what OS are we running on?
$osString = $^O;

#parse the command line for commands and arguments
ReadArguments;

if ($progressOpt) {
   print $lst, "Executing this script on a computer running $osString...\n";
}

#initialize these counter variables
$fileCount = 0;
$dirCount = 0;
$unknownCount = 0;
$errorCount = 0;
$foundCount = 0;

#process every directory (and/or file) provided on the command line
while (@ARGV) {
   $arg = shift(@ARGV);  #get the next directory/file to examine
   if ((-f $arg) || (-d $arg)) {  #check for a valid disk entity
      File::Find::find(\&SearchFilter, $arg);  #'find' calls "SearchFilter"
   }   #which we use as a filter and to call our "DoAFile".
   else {
      $unknownCount++;
      print STDERR "# ERROR: \"$arg\" wasn't a recognized file or
directory.\n";
   }
}

if ($progressOpt || $summaryInfoOnly || $countOnlyOpt) {
   print $lst, "FOUND $foundCount occurrances of \"$expression\" ";
   print "in the specified files.\n";
}
if ($progressOpt || $summaryInfoOnly) {
   print $lst, "Examined $fileCount files, and $dirCount directories";
   if ($errorCount > 0) {
      print " -- encountered $errorCount errors";
   }
   print ".\n";
   if ($unknownCount > 0) {
      print $lst, "There were $unknownCount ";
      print "non-files/non-directories encountered.\n";
   }
   print "\n";
}
exit;

#========================================================================
#========================================================================



***** Want to unsubscribe from this list?
***** Send mail with body "unsubscribe" to mac-perl-request@iis.ee.ethz.ch