4

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.

Jared Oberhaus
  • 596
  • 6
  • 14

4 Answers4

9

You can do it with extended globbing.

shopt -s extglob

then

rm !(file.tar)

This works in bash 3.2.39 at a minimum

Cian
  • 5,777
  • 1
  • 27
  • 40
  • 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
  • Hi @Cian, was hoping to maximize votes for your answer. My unproven theory is that people are more likely to vote for the right answer when it isn't yet the accepted answer. But I see that after I accepted your answer, you immediately got another vote :) – Jared Oberhaus Jul 16 '09 at 20:41
0

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.

Zoredache
  • 128,755
  • 40
  • 271
  • 413
0

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 {} +
Dan Carley
  • 25,189
  • 5
  • 52
  • 70
  • 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
0

Edit:

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(.)

Non-Recursive:

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
Kyle Brandt
  • 82,107
  • 71
  • 302
  • 444