[Chapter 18] 18.10 There's More than One Way to Do It
Author: Jerry Peek, Tim O'Reilly & Mike Loukides
Date: 1998-08-04T21:39:06Z

#

| Chapter 18 Linking, Renaming, and Copying Files |

## 18.10 There's More than One Way to Do It

[In article 18.9, Jerry Peek shows how if you really understand the shell and utilities like sed, you can easily construct custom commands to change one set of filenames to another according to some regular pattern. In article 18.11, Linda Mui explains a C program that makes the job easier - and has some built-in safeguards that prevent any renames if some of the moves could cause problems. Here, Larry Wall and Randal Schwartz present a Perl (37.1) script that gives you a different kind of power and flexibility. By the way, that's the Perl slogan: "There's more than one way to do it." -TOR ]

rename | There are many ways of renaming multiple files under UNIX. Most of these ways are kludges. They force you to use ad hoc shell variable modifiers or multiple processes. With the rename Perl script, you can rename files according to the rule specified as the first argument. The argument is simply a Perl expression that is expected to modify the `$_` string in Perl [the current input line-TOR ] for at least some of the filenames specified. Thus you can rename files using the very same `s///` notation you're already familiar with (34.24). If a given filename is not modified by the expression, it will not be renamed. If no filenames are given on the command line, filenames will be read via standard input.

For example, to rename all files matching `*.bak` to strip the extension, you might say:

>     % rename 's/\.bak$//' *.bak

But you're not limited to simple substitutions - you have at your disposal the full expressive power of Perl. To add those extensions back on, for instance, say this:

>     % rename '$_ .= ".bak"' *

or even:

>     % rename 's/$/.bak/' *

To translate uppercase names to lowercase, you'd use:

>     % rename 'tr/A-Z/a-z/' *

And how about these?

>     % rename 's/foo/bar/; $_ = $was if -e' *foo*

>     % find . -print | rename 's/readme/README/i'

>     % find . -print | rename 's/$/.old/ if -M $_ > 0.5'

>     % find . -name '*,v' -print | \
>       rename 's#(.*)/#$1/RCS/#, $x{$1}++ || mkdir("$1/RCS", 0777)'

[Of course, to even understand some of these more complex incantations, you have to learn more about Perl, which is just the point... It's worth taking the time to learn. -TOR ]

- LW, RS

18.9 Renaming, Copying, or Comparing a Set of Files |  | 18.11 Renaming Files with ren