Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a lot of files and folders in a specific folder and I want to delete all of them; however, I wanted to keep files X, Y, and Z.

Is there a way I can do something like: rm * | but NOT grep | X or Y or Z

share|improve this question
I assume I can use some regular expression in there that will do this? – Amit Feb 10 '11 at 22:46
up vote 12 down vote accepted

Instead of using rm, it may be easier to use find. A command like this would delete everything except a file named exactly 'file'

find . \! -name 'file' -delete

Many versions of should be able to support globbing and regular expression matching.

You could also pipe the output of find to rm as well

find . \! -name '*pattern*' -print0 | xargs --null rm 
share|improve this answer
And this lets you see exactly what files will be deleted by removing the -delete as well as what files will be saved by removing -delete and the \!. – Shawn J. Goff Feb 11 '11 at 0:51
careful, find is recursive! so all files subdirectories not matching 'pattern' will get deleted as well – Alexandre Holden Daly Jun 23 '14 at 22:07

Using zsh, with setopt EXTENDED_GLOB

rm *~{x,y,z}

But, you should probably instead move the files elsewhere, then delete everything. It's far safer in terms of finger slips, such as hitting enter too soon.

share|improve this answer
+1 for your last paragraph – glenn jackman Feb 11 '11 at 14:01

Later versions of bash have the extglob shell option that gives you a syntax for doing what you want (check your man page under "Pathname Expansion" to see if your installed version has it):

$ shopt -s extglob  # turn on extended globbing
$ rm !(X|Y|Z)

To test, I suggest you first replace rm with echo to see if the list of files to be deleted is what you expect.

share|improve this answer
ls -1 | grep -v "^[XYZ]$" # | xargs rm -r

Attention: Run the command and if the files to be deleted are the right ones, run it again and delete the hash character "#".

If the filenames are more complicated then that, do

ls -1 | egrep -v "^file1$|^filename2$|^f1le$" # | xargs rm -r

Again, first look at the results then remove the hash sign.

This version - as suggested in the comments - saves some characters and looks a bit clearer.

ls -1 | egrep -v "^(file1|filename2|f1le)$" # | xargs rm -r
share|improve this answer
A suggested edit by ddeimeke is to change the egrep argument to "^(file1|filename2|f1le)$" – Michael Mrozek Feb 11 '11 at 22:37
If you have three files a, b and a b the first program will delete - if you put ab into the grep part: "^[ab]$" a and b but not a b, just opposed to your intentions. The second command will do the same. And the third too. You shouldn't use 'ls' in scripts, with very, very rare exceptions. Just don't do it. – user unknown Mar 12 '11 at 2:17

Move the files you want to keep away. Go up one level, delete the folder. Re-create the folder and move those files back.

share|improve this answer
I wonder why the minus?.. It's actually both easier and safer than anything proposed by others: you simply can't shoot yourself in a foot by hitting some special char in the filename. – alex Feb 11 '11 at 8:34
a) You move your file X one directory up, where a file X exists - silently deleted, gone. b) You're in the top dir, where no 'up' exists. c) You're in your home, and don't have permission to write to /home. If you put your advice into a script, and tested it without problem, and use it in such a situation - peng! – user unknown Mar 12 '11 at 2:38
a) Hey, did I say 'move files up one level'? I've said move them away. b) So you're trying to remove all files in /, heh? Not very practical. c) Trying to remove all files in your $HOME isn't really practical either. – alex Mar 12 '11 at 6:48
You're right, I'm sorry. – user unknown Mar 12 '11 at 7:14
 find tmp -not -name X -not -name Y -not -name Z -delete 
share|improve this answer
If X, Y or Z is a directory, this will delete files inside them as well. find tmp -maxdepth 1 -not -name X -not -name Y -not -name Z -delete is one way to work around this. – Gilles Mar 12 '11 at 1:00
Since folders under Unix are files (anything is a file), that's maybe what is intended. The question explicitly says: "I have a lot of files and folders in a specific folder and I want to delete all of them; " - and if you like to exclude Y, maybe you know whether Y is a directory or not. – user unknown Mar 12 '11 at 1:37

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.