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