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

[MacPerl] File conversion script 2.2




Thank you everyone that sent in suggestions, and also
their own scripts . . . all are very much appreciated!

Special thanks to Ronald Kimball who took the time to
really pick over the original Convert script I wrote
and offer some very good suggestions.

Hope this is of some benefit to a few of you.

Additional comments are always welcome.

Ero Brown



#========================================================================
#========================================================================
#
# Convert.pl
#
# Author: Ero Brown <ero@fiber.net>
#
# Version: 2.2
#
# Special thanks to Ronald J. Kimball who's suggestions helped
# make this a much better script.  Also thanks to Chris Nandor
# and Christian Brechbuehler 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 [-p] [-r] [-t <fType>] [-c <fCreator>] [-f <expression>]
                            -x <translation> <folder(s) &| file(s) . . .>
   -p   print progress information
   -r   recursively process encountered sub-directories
   -t   set the file type (on MacOs only) e.g., 'TEXT'
   -c   set the file creator (on MacOs only) e.g., 'R*ch'
   -f   file expression representing a file filter
   -x   translation to be performed, where <translation> is:
           ToDos = convert to a DOS format
           ToMac = convert to a Mac format
           ToUnx = convert to a Unix format

   *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", "p",
                           "t=s" => \$fType,
                           "c=s" => \$fCreator,
                           "f=s" => \$fileFilter,
                           "x=s" => \$translation);
   if (!$res) {
      Usage;
   }

   #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;
   }

   $recurseOpt = $opt_r;
   $progressOpt = $opt_p;
   $fixTypeOpt = $fType ne '';
   $fixCreatorOpt = $fCreator ne '';
   $fileFilterOpt = $fileFilter ne '';

   if ($translation eq '') {
      print "The required -t (translation) option was NOT specified.\n";
      Usage;
   }
   if ($fixCreatorOpt && ($osString ne 'MacOS')) {
      print "Must be running MacOs in order to set the creator of a file.\n";
      Usage;
   }
   if ($fixTypeOpt && ($osString ne 'MacOS')) {
      print "Must be running MacOs in order to set the type of a file.\n";
      Usage;
   }

   if ($osString eq 'MacOS') {
      if ($fixTypeOpt && ((length($fType)) != 4)) {
         print "\"$fType\" is not a valid file creator designator.\n";
         Usage;
      }
      if ($fixCreatorOpt && ((length($fCreator)) != 4)) {
         print "\"$fCreator\" is not a valid file creator designator.\n";
         Usage;
      }
      if ($fixTypeOpt || $fixCreatorOpt) {
         if (!$fixTypeOpt) {
            $fType = 'TEXT';
         }
         if (!$fixCreatorOpt) {
            $fCreator = 'R*ch';
         }
      }
   }

   $translation =~ s/To//i;
   $translation =~ s/Pc/Dos/gi;
   $translation =~ s/Unix/Unx/gi;
   if ($translation =~ /Dos/i) {
      $fromExpression = "(\x0D\x0A?|\x0A)";
      $toExpression = "\x0D\x0A";
   }
   elsif ($translation =~ /Mac/i) {
      $fromExpression = "\x0D?\x0A";
      $toExpression = "\x0D";
   }
   elsif ($translation =~ /Unx/i) {
      $fromExpression = "\x0D\x0A?";
      $toExpression = "\x0A";
   }
   else {
      print "Unknown -t (translation) option was 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 ($result, $filestr, $shortName, $doSearch);

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

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

      $result = "";
      if ($doSearch) {
         if ($progressOpt) {
            print "\t$shortName is about to be opened and searched.\n";
         }
         if (open(THEFILE, "< $theFile\0")) {
            $result = "";
            while ($filestr= <THEFILE>) {
               $filestr =~ s/$fromExpression/$toExpression/g;
               $result = join('',$result,$filestr);
            }
            close(THEFILE);

            if (($fixTypeOpt || $fixCreatorOpt) && ($osString eq 'MacOS')) {
               MacPerl::SetFileInfo($fCreator, $fType, $theFile);
            }

            if (open(THEFILE, "> $theFile\0")) {
               print THEFILE $result;
               close(THEFILE);
               $processedCount++;
               if ($progressOpt) {
                  print "\tChanged file: $shortName\n";
               }
            }
            else {
               $errorCount++;
               print STDERR "ERROR: Couldn't write to: \"$theFile\" -- $!\n";
            }
         }
         else {
            $errorCount++;
            print STDERR "ERROR: Couldn't open: \"$theFile\" -- $!\n";
         }
      }
   }
   # it must be a directory (-d $theFile)
   else {
      $dirCount++;
   }
}


#========================================================================
# 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 $_ && -w $_ && -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;

#set the paragraph mode to search accross regular line endings
$/ = "\n\n";   # enable paragraph mode

#parse the command line for commands and arguments
ReadArguments;

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

#initialize these counter variables
$fileCount = 0;
$dirCount = 0;
$processedCount = 0;
$errorCount = 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) {
      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) {
   print "Changed $processedCount files to the $translation format.\n";

   print "Examined $fileCount files, in $dirCount directories";
   if ($errorCount > 0) {
      print " -- encountered $errorCount errors";
   }
   print ".\n";

   if ($unknownCount > 0) {
      print "There were $unknownCount 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