You have a lot of files whose names you want to change.
Use a foreach
loop and the rename
function:
foreach $file (@NAMES) { my $newname = $file; # change $newname rename($file, $newname) or warn "Couldn't rename $file to $newname: $!\n"; }
This is straightforward. rename
takes two arguments. The first is the filename to change, and the second is its new name. Perl's rename
is a front end to the operating system's rename system call, which typically won't let you rename files across filesystem boundaries.
A small change turns this into a generic rename
script, such as the one by Larry Wall shown in Example 9.5.
#!/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 $_; }
This script's first argument is Perl code that alters the filename (stored in $_
) to reflect how you want the file renamed. It can do this because it uses an eval
to do the hard work. It also skips rename
calls when the filename is untouched. This lets you simply use wildcards like rename
EXPR
*
instead of making long lists of filenames.
Here are five examples of calling the rename program from your shell:
% rename 's/\.orig$//' *.orig % rename 'tr/A-Z/a-z/ unless /^Make/' * % rename '$_ .= ".bad"' *.f % rename 'print "$_: "; s/foo/bar/ if <STDIN> =~ /^y/i' * % find /tmp -name '*~' -print | rename 's/^(.+)~$/.#$1/'
The first shell command removes a trailing ".orig"
from each filename.
The second converts uppercase to lowercase. Because a translation is used rather than the lc
function, this conversion won't be locale-aware. To fix that, you'd have to write:
% rename 'use locale; $_ = lc($_) unless /^Make/' *
The third appends ".bad"
to each Fortran file ending in ".f"
, something a lot of us have wanted to do for a long time.
The fourth prompts the user for the change. Each file's name is printed to standard output and a response is read from standard input. If the user types something starting with a "y"
or "Y"
, any "foo"
in the filename is changed to "bar"
.
The fifth uses find to locate files in /tmp
that end with a tilde. It renames these so that instead of ending with a tilde, they start with a dot and a pound sign. In effect, this switches between two common conventions for backup files.
The rename script exemplifies the powerful Unix tool-and-filter philosophy. Even though we could have created a dedicated command to do the lowercase conversion, it's nearly as easy to write a flexible, reusable tool by embedding an eval
. By allowing the filenames to be read from standard input, we don't have to build in the recursive directory walk. Instead, we just use find, which performs this function well. There's no reason to recreate the wheel, although using File::Find we could have.
The rename
function in perlfunc (1) and in Chapter 3 of Programming Perl; your system's mv (1) and rename (2) manpages; the documentation for the standard File::Find module (also in Chapter 7 of Programming Perl)