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