Server Fault is a question and answer site for system and network administrators. 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

For instance, I want to remove all the files in a directory except for the .tar file from whence they came. I could do something like:

find . -maxdepth 0 | grep -v '.tar$' | xargs rm -f

but is there a way to do is just using rm and shell pattern matching? Feel free to specify it using bash or other commonly available shells, or with extended options, if it can't be done with vanilla sh.

I found a similar question about avoiding directories and subdirectories with find, but not with shell patterns.

share|improve this question
up vote 8 down vote accepted

You can do it with extended globbing.

shopt -s extglob


rm !(file.tar)

This works in bash 3.2.39 at a minimum

share|improve this answer
This is the only answer so far that addresses the question with an answer. Thanks Cian... – Jared Oberhaus Jul 16 '09 at 19:16
Can you accept my answer please? :-P – Cian Jul 16 '09 at 19:43
Is that recursive? When I run a similar command with ls it appears to be. If so, um, be very careful. – Telemachus Jul 16 '09 at 19:44
@telemachus doesn't appear to be when I try it. It may depend on whether you have globstar turned on though. – Cian Jul 16 '09 at 19:53
Telemachus: I don't think its recursive, it would just include directories as well. ls expands directories u.nless you use the -d switch – Kyle Brandt Jul 16 '09 at 19:55

I don't think what you want to achieve is possible.

You could however simplify the command you have:

find . -maxdepth 0 -not -name '*.tar' -exec rm -f {} +
share|improve this answer
Possible, but if you get it slightly wrong, look out. I wouldn't really recommend it, though I know you're just trying to answer the OP's request. – Telemachus Jul 16 '09 at 19:01

Try this perhaps

find . -maxdepth 0 \! -name '*.tar' -exec echo rm -f {} \;

Remove the echo preceding the rm if it looks right.

Yes, but is there a shell pattern?

I don't think so. At least not in the versions of bash I am familiar with. From the other answers it appears that newer versions may be more functional.

share|improve this answer
Wildcard on the end of tar doesn't match the original regex anchor. I presume the OP was using egrep. – Dan Carley Jul 16 '09 at 18:54
You can do it with extglobbing in bash. – Cian Jul 16 '09 at 19:10


Read the question to fast... But in to continue with my post anyways... :-) If you want to delete all files but tar files recursively with zsh:

rm -rf **/^*.tar(.)


rm -rf ^*.tar(.)

The new bash 4.0 and and zsh support recursive globbing. To enable it in bash use:

shopt -s globstar

It works like:

 rm -rf **/*.tar.gz
share|improve this answer
Wow. That gives me all kinds of fear :D – Dan Carley Jul 16 '09 at 19:05
Um, yes, that doesn't seem like a good idea at all. – Telemachus Jul 16 '09 at 19:47
Why not, just use it with echo first to make sure You don't delete the wrong stuff... – Kyle Brandt Jul 16 '09 at 19:53
Use it with echo first is always good advice, but I suppose I worry a lot about that one time when you're going too quickly and forget echo. **/ makes me nervous for destructive commands. – Telemachus Jul 16 '09 at 20:06

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.