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 u and p. Is there an easy way to do this?
- 103
- 4
- 1,469
17 Answers
To rm all but u,p in bash just type:
rm !(u|p)
This requires the following option to be set:
shopt -s extglob
See more: glob - Greg's Wiki
What I do in those cases is to type
rm *
Then I press Ctrl+X,* to expand * into all visible file names.
Then I can just remove the two files I like to keep from the list and finally execute the command line.
- 89,072
- 65
- 269
- 311
You can use find
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
Update
- Keep in mind that the order of the elements of the expressions is significant (see the documentation)
Test your command first by using
-printinstead of-deletefind . ! -name u ! -name p -maxdepth 1 -type f -print
- 107
- 8,097
- 3
- 47
- 58
Simple:
mv the files you want in a upper directory, rm the directory and then mv them back.
- 617
Somewhat similar to this answer but no special options are needed, as far as I know the following is "ancient" functionality supported by any (vaguely) /bin/sh resembling shell (e.g. bash, zsh, ksh, etc)
rm [^up]
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.
In zsh:
setopt extended_glob # probably in your .zshrc
then
rm ^(u|p)
or
rm *~(u|p)
The second will work even if you have ^ in $histchars for history substitution, and of course you can put an arbitrary glob before the ~.
- 193
Use:
find . -type f ! -name 'u' ! -name 'p' ! -name '*.ext' -delete
find . -type d ! -name 'u' ! -name 'p' ! -name '*.ext' -delete
in order to delete all files including directories, except u, p and .ext files.
- 31
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.
- 305
find . -maxdepth 1 ! -name "u" ! -name "p" -type f -exec rm -rf {} \;
This will delete all files except u and p in unix
- 26,529
- 131
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 u and 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
Yet another:
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.
- 251
Here's another variant. You can type:
rm -i *
or:
rm --interactive *
So rm will ask you to confirm deleting of each file.
- 21
I always use:
rm [a-o,q-t,v-z]*
This will allow you to define how granular you want to make it. So if you want to delete a through o and Z files you can use:
rm [a-o,z]*
- 920
Yet another version using xargs:
ls -1 | grep -v do_not_delete | xargs -I files rm "files"
Note that xargs -I is needed to handle filenames including spaces correctly.
- 111
A simple way that is hard to mess up: let's say you want to delete everything except *.pdf:
mkdir tmp
mv *.pdf tmp
rm *
mv tmp/* .
rm -r tmp
- 121