## 10.9. Renaming, Copying, or Comparing a Set of Files

If you have a group of files whose names end with .new and you want to rename them to end with .old, you might try something like the following:

>     % mv *.new *.old Wrong!

However, this won't work because the shell can't match *.old and because the mv command just doesn't work that way. Here's one way to do it that will work with most shells:

`-d` Section 8.5, `\(..\)..\1` Section 34.11

>     $ ls -d *.new | sed "s/\(.*\)\.new$/mv '&' '\1.old'/" | sh
>     % ls -d *.new | sed 's/\(.*\)\.new$/mv "&" "\1.old"/' | sh

That outputs a series of mv commands, one per file, and pipes them to a shell (Section 3.4). The quotes help make sure that special characters (Section 27.17) aren't touched by the shell -- this isn't always needed, but it's a good idea if you aren't sure what files you'll be renaming. Single quotes around the filenames are "strongest"; we use them in the Bourne-type shell version. Unfortunately, csh and tcsh don't allow `$` inside double quotes unless it's the start of a shell variable name. So the C shell version puts double quotes around the filenames -- but the Bourne shell version can use the "stronger" single quotes, like this:

>     mv 'afile.new' 'afile.old'
>     mv 'bfile.new' 'bfile.old'
>        ...

To copy, change mv to cp. For safety, use mv -i or cp -i if your versions have the -i options (Section 14.15). Using sh -v (Section 27.15) will show the commands as the shell executes them.

This method works for any Unix command that takes a pair of filenames. For instance, to compare a set of files in the current directory with the original files in the /usr/local/src directory, use diff:

>     % ls -d *.c *.h | sed 's@.*@diff -c & /usr/local/src/&@' | sh

Note that diff -r does let you compare entire directories, but you need a trick like this to only compare some of the files.

--JP and DJPH

Copyright © 2003 O'Reilly & Associates. All rights reserved.