Tuesday, November 25, 2008

A perl script to rename your files

For those of you looking for a cool way to rename your files, here is a little script that could work wonders for you.

Basically, this scripts takes in a PERL substitution expression and applies it to the filename of interest.

To get started, copy the script below into a file called 'rename.pl'. Once you have done that, then read the usage instructions by running the script with the '-h' option. Of course, you will need perl installed on your machine.

So why write this script? Because I got sick and tired of manually renaming files by hand. Some people have files called 'some_file.txt'. I prefer that file to be called 'SomeFile.txt'.

To accomplish this, all I have to do is run the script like so:

   perl rename.pl -u "s/_/ /g" some_file.txt


followed by
   perl rename.pl "s/ //g" "Some File.txt"


Note: The -u option causes the first letter of each word separated by a space to be capitalized.

Okay, maybe its quicker to manually do this for a single file, but if you are on Windows and have a whole folder full of files like that, then the process is:

   for %v in (*.txt) do perl rename.pl -u "s/_/ /g" "%v" 
   for %v in (*.txt) do perl rename.pl "s/ //g" "%v"


That is all there is to it! All of the files will be renamed with 'camel' text names.

Please make sure that before you attempt to batch rename files, that you have them backed up first!

Script start [hint: dont copy this line ;-)]
#!/usr/bin/perl -w

BEGIN {
 use Getopt::Std;
 use vars qw/ $opt_h $opt_u /;
 getopt;

 # usage
        sub usage {
  print STDOUT <<'END_OF_USAGE';

  Usage: rename [-hu] sub_regex [files]

                sub_regex is any expression that you would like to
                apply to filename. You can use capturing or just 
                matching.

                -h .... shows this message ;-)
                -u .... makes first letter of each word uppercase

  examples:

                1.
         perl rename.pl "s/_/ /g" rename_me.txt
                   This renames rename_me.txt to "rename me.txt"

                2.
         perl rename.pl -u "s/_/ /g" rename_me.txt
                   This renames rename_me.txt to "Rename Me.txt"

                3. MS Windows example
         for %v in (*.mp3) do perl rename.pl -u "s/_/ /g" "%v"
                   This renames all mp3 files in the current directory such that
                   every word begins with a capital letter and all underscores
                   are replaced with spaces.


END_OF_USAGE

}
 if ($opt_h) {
                usage();
  exit(0);
 }

}

# get the substition regex
$op = shift or (usage() and exit(1));

# go through file names
chomp(@ARGV) unless @ARGV;
for (@ARGV) {
    $was = $_;
    eval $op;
    die $@ if $@;
    # cap first letter of each word
    my $newname = "";
    my @components = split(/ /, $_);
    foreach (@components) {
      my $x = $_;
      $x = ucfirst lc $x if $opt_u;
      if ($newname eq "") {
         $newname = "$x";
      } else { 
         $newname .= " $x";
      }
    }
    rename($was,$newname) unless $was eq $newname;
}

Script End [hint: dont copy this line ;-)]

7 comments:

Stewart said...

Wow!

This certainly makes a good point. I'd like to see the response of others on this topic. Makes interesting reading. Thanks a lot for sharing it. :)

Perl Script

Anonymous said...
This comment has been removed by a blog administrator.
shaik said...

Hi Can you suggest me teh progrm in perl..for the same logic in Windows...

Thanks
Shaik

Bharat said...

Running this script prompts error like this

$ perl renaming.pl

syntax error at renaming.pl line 52, near "= ) "
Execution of renaming.pl aborted due to compilation errors.

Ed said...

It has been fixed. There was an erroneous '=' character in the script...

Rick said...

Perhaps I'm missing something but there seems to be a small bug here: when I try to simply rename the files, changing the initial letter to uppercase, I end up with a filename prepended with a space (I didn't think that was possible but on my Mac it apparently is).

Here's what I do:
Given files:
a.png
b.png
c.png

rename.pl -u "s///g" *png

I end up with:
A.png
B.png
C.png

(note initial space char).

I looked at the code more closely and believe the space is coming from line 63:

$newname .= " $x";

When I remove the space in front of the variable assignment, the script works fine:

$newname .= "$x";

Or am I just not providing the right regexp?

Ed said...

Looks like you are correct. Except when renaming something with whitespace in the name. I will update this example in a day or so to handle whitespace correclty