14.18. Removing Every File but One
One problem with Unix: it's not terribly good at "excluding" things. There's no option to rm that says, "Do what you will with everything else, but please don't delete these files." You can sometimes create a wildcard expression (Section 33.2) that does what you want -- but sometimes that's a lot of work, or maybe even impossible.
Here's one place where Unix's command substitution ( Section 28.14) operators (backquotes) come to the rescue. You can use ls to list all the files, pipe the output into a grep -v or egrep -v (Section 13.3) command, and then use backquotes to give the resulting list to rm. Here's what this command would look like:
% rm -i `ls -d *.txt | grep -v '^john\.txt$'`
This command deletes all files whose names end in .txt, except for john.txt. I've probably been more careful than necessary about making sure there aren't any extraneous matches; in most cases, grep -v john would probably suffice. Using ls -d (Section 8.5) makes sure that ls doesn't look into any subdirectories and give you those filenames. The rm -i asks you before removing each file; if you're sure of yourself, omit the -i.
Of course, if you want to exclude two files, you can do that with egrep:
% rm `ls -d *.txt | egrep -v 'john|mary'`
(Don't forget to quote the vertical bar (|), as shown earlier, to prevent the shell from piping egrep's output to mary.)
Another solution is the nom (Section 33.8) script.
Copyright © 2003 O'Reilly & Associates. All rights reserved.