Page 1 of 1

Quick Recursive File Rename Script Rate Topic: -----

#1 auggiecc87  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 6
  • View blog
  • Posts: 48
  • Joined: 09-March 09

Posted 13 September 2010 - 02:11 PM

I created this script for use in a file update at work. It uses Perl to go through the files in a directory and update the files of a certain name with a new name. This script is recursive but skips the . .. and .svn directories.

i.e. old_file.txt -> new_file.txt
The script takes 3 command line inputs from the user:
Argv[0] is the old file name to find
Argv[1] is the new file name to replace with
Argv[2] is an optional directory location. If one is not supplied it assumes current directory was desired

I'm sure there are edge/error cases that this code does not handle but it does work successfully.
I even included a cute little -h option that prints the usage to the command line.

Note: The commented out lines were used to make sure the code was working as I expected but can also be used to make sure all the files changed were expected/wanted.

Now for the step through.
I recommend using at minimum strict. Also wouldn't be a bad habit to use warnings when using perl. Now to the code standard setup
#!/local/bin/perl
use strict;
use warnings;
use Cwd;



Let's add a -h for usage bit.

if ($ARGV[0] =~ /-h/){
  print "Usage:  ARGV[0] is the file name to search for in this directory
  and all subdirectories
ARGV[1] is the new file name wanted for these files
ARGV[2] is the directory to use as the toplevel. This is optional and if it
  isn't specified it will use the current directory as the base \n";
  exit;
}



We need to check that the script is being called with the proper arguments so
do {
  print "use -h for help\n";
  exit;
} unless defined($ARGV[0] && $ARGV[1]);


This checks to see that the arguments we need are set and if they are not then tells the user that they have used an incorrect call of this file.

So now we set some variables needed. On a *nix system the file deliminator willbe "/" so we tell our script that. Also we get the current directory name incase the user didn't specify a directory. This facilitates the "use Cwd;" we included earlier
our ${fd}= "/";
my $dir = getcwd;


Now we set variables based on the user input
my $searchfor = $ARGV[0];
my $rename = $ARGV[1];
# print "$searchfor $rename \n";
if ($ARGV[2]){
  $dir = $ARGV[2];
}


and then call our subfunction that will actually do the work
runThisDirectory($dir);



Now we must declare this subfunction and get the files under this directory. Here you will see that I use a grep for ".", "..", and ".svn" to prevent the current directory and its parent directory as well as the .svn directory from being recursed into.
sub runThisDirectory {
  my $mine = "$_[0]";
  opendir THIS_DIR, $mine;
  my @dirlist = sort(grep !/^\.$/, grep !/^\.\.$/, grep !/^\.svn$/, readdir THIS_DIR);
  closedir THIS_DIR;


Now we have a list of the files under this directory. We can check to see if the file has the name we are trying to replace and if it does change the name
  foreach my $file (@dirlist){
#    print "$file \n";
    if ($file eq $searchfor){
      `mv $mine${fd}$file $mine${fd}$rename`;
#      print "mv $mine${fd}$file $mine${fd}$rename in $mine \n";
    }


But we also want to check if the filename is that of a directory. If it is then we want to run this directory recursively.
    elsif (-d "$mine${fd}$file"){ #if the file is a subdir run it recursively
      runThisDirectory("$mine${fd}$file");
    }
  } #end sub runThisDirectory


And now you are finished. Go check it out.

Is This A Good Question/Topic? 0
  • +

Page 1 of 1