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
)