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.


You can do it with extended globbing.

shopt -s extglob


rm !(file.tar)

This works in bash 3.2.39 at a minimum

  • This is the only answer so far that addresses the question with an answer. Thanks Cian... – Jared Oberhaus Jul 16 '09 at 19:16
  • 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
  • @Kyle: facepalm. I'm an idiot and clearly am not thinking very quickly. Thanks, that was it. – Telemachus Jul 16 '09 at 20:04

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 {} +
  • 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.

  • 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
  • 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 clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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