I need to delete all files in a directory, but exclude some of them. For example, in a directory with the files
a b c ... z, I need to delete all except for
p. Is there an easy way to do this?
You can use
find . ! -name u ! -name p -maxdepth 1 -type f -delete
!negates the next expression
-namespecifies a filename
-maxdepth 1will make find process the specified directory only (
findby default traverses directories)
-type fwill process only files (and not for example directories)
-deletewill delete the files
You can then tune the conditions looking at the man page of find
- Keep in mind that the order of the elements of the expressions is significant (see the documentation)
Test your command first by using
find . ! -name u ! -name p -maxdepth 1 -type f -print
Doing it without find:
ls | grep -v '(u|p)' | xargs rm
(Edit: "u" and "v", as in other places here, are being used as generic versions of entire regexes. Obviously you'll want to be careful to anchor your regexes to avoid matching too many things.)
You're definitely going to want a script if you're going to be doing much of this, as others have suggested.
Back in the floppy era I had a dos executable called "Except" that would move things out of the current directory temporarially and execute a command, so you could say:
except *.txt del *.*
to delete everything but your text files.
This would be a pretty trivial thing to implement as a shell script and if this is the kind of thing you are likely to do more than twice it seems like it would be a good idea.
For those preferring to specify arbitrary complex exclude patterns (spanning all affected filenames) in a full blown regexp emacs, posix-awk or posix-extended style (see find man page) I would recommend this one. It excludes
p in current dir in this example. This may be handy for scripts.
find -regextype posix-awk ! -regex './(u|p)' -print0 | xargs -0 rm -rf
for FILE in ./*; do if [[ $FILE != ./u* ]] || [[ $FILE != ./p* ]];then rm $FILE; fi; done;
It's kind of lengthy and I don't know if you could easily make it into an function that could easily accommodate and arbitrary number of arguments, but it works well.
And it's pure bash goodness.