[Novalug] changing file names

Michael Henry lug-user at drmikehenry.com
Wed Nov 25 09:04:52 EST 2009


On 11/23/2009 10:39 PM, Nino Pereira wrote:
> I have a long list of files without extensions. I want to
> add an extension (like .pdf or .jpg or .gif). How do you do that?

Though you've already gotten several answers, I wanted to
mention my favorite tool for this job.  Larry Wall, the creator
of Perl, came up with this compact gem, "Larry's filename
fixer":

#!/usr/bin/perl -w
# rename - Larry's filename fixer
$op = shift or die "Usage: rename expr [files]\n";
chomp(@ARGV = <STDIN>) unless @ARGV;
for (@ARGV) {
    $was = $_;
    eval $op;
    die $@ if $@;
    rename($was,$_) unless $was eq $_;
}

I generally save this script under the name 'ren' in my ~/bin
directory to avoid colliding with "rename", a similar script
that's part of some distributions of Linux.

Despite its brevity, it packs a powerful punch.  The basic idea
is to iterate through filenames supplied either as command-line
arguments or via standard input, applying a user-supplied
snippet of Perl to transform the filename.  If the transformed
name is different from the original, the script renames the
file.

This tool requires at least a rudimentary knowledge of Perl
regular expressions to be truly powerful.

I most commonly use the Perl substitute operator
(s/regex/replacement/) with this script.  To accomplish the
original poster's task, the invocation would be:

  ren 's/$/.pdf/' *

The first argument is the snippet of Perl that transforms the
filenames.  It should generally be quoted with apostrophes to
protect it from shell expansion.  The second argument is just a
standard filename glob that the shell will expand into the list
of filenames to rename.  The substitute command matches a
portion of the input filename against a regular expression
(regex).  In this case, the regular expression is just '$',
which matches the end of the filename.  The matched portion of
the filename is then replaced with the replacement text.  In
this case, that's '.pdf'.  So "original" becomes "original.pdf".

I've often used this tool to replace spaces in filenames with
underscores.  For example:

  $ touch "a name with multiple words"
  $ ls -Q
  "a name with multiple words"
  $ ren 's/ /_/g' *
  $ ls -Q
  "a_name_with_multiple_words"

Or to downcase extensions like ".TXT" into ".txt":

  $ touch {one,two,three}.TXT
  $ ls
  one.TXT  three.TXT  two.TXT
  $ ren 's/\.TXT$/.txt/' *
  $ ls
  one.txt  three.txt  two.txt

Or with Perl's "lc" function to make strings lowercase, the
entire filename can be downcased using fancier Perl that I
always have to lookup :-)

  $ touch {ONE,TWO,THREE}.TXT
  $ ls
  ONE.TXT  THREE.TXT  TWO.TXT
  $ ren 's/.*/lc($&)/e' *
  $ ls
  one.txt  three.txt  two.txt

Because the script lets you insert arbitrary Perl code into the
filename transformation process, the sky's the limit.  But for
daily use, I find it worth memorizing this construct:

  ren 's/regex/replacement/g' *

Coupled with basic knowledge of Perl regular expressions, it can
handle most of my renaming needs without hitting the Perl
documentation.

Michael Henry




More information about the Novalug mailing list