foreach my $file (glob "*.old") {
my $newfile = $file;
$newfile =~ s/\.old$/.new/;
if (-e $newfile) {
warn "can't rename $file to $newfile: $newfile exists\n";
} elsif (rename $file, $newfile) {
## success, do nothing
} else {
warn "rename $file to $newfile failed: $!\n";
}
}
The check for the existence of $newfile is needed
because rename will happily rename a file right
over the top of an existing file, presuming the user has permission
to remove the destination filename. We put the check in so that
it's less likely that we'll lose information this way. Of
course, if you wanted to replace existing files
like wilma.new, you wouldn't bother
testing with -e first.
Those first two lines inside the loop can be combined (and often are)
to simply be:
(my $newfile = $file) =~ s/\.old$/.new/;
This works to declare $newfile, copy its initial
value from $file, then select
$newfile to be modified by the substitution. You
can read this as "transform $file to
$newfile using this replacement on the
right." And yes, because of precedence, those parentheses are
required.
Also, some programmers seeing this substitution for the first time
wonder why the backslash is needed on the left, but not on the right.
The two sides aren't symmetrical: the left part of a
substitution is a regular expression, and the right part is a
double-quotish string. So we use the pattern
/\.old$/ to mean ".old
anchored at the end of the string" (anchored at the end,
because we don't want to rename the first
occurrance of .old in a file called
betty.old.old), but on the right we can simply
write .new to make the replacement.
 |  |  |
13. Manipulating Files and Directories |  | 13.3. Links and Files |