I'm trying to delete all subdirectories of my current working directory which contain a rar file.

My first attempt: find -name *.rar -exec rm -r {}/.. ';' failed because that is not a valid directory. I tried using dirname {} for a more sensible command, but decided to just ask after almost deleting stuff I didn't mean to.

I'm using Cygwin on Windows 7.


You could do it with a pair of statements.

First, get a list of directories to remove using

find -name *.rar -exec dirname {} ';' > toremove

Next, cat toremove to make sure it has the folders you want. Then, pass it to rm -rf using

sed 's/^/"/g' toremove | sed 's/$/"/g' | xargs rm -r

Last, rm toremove.

  • 1
    Excellent tip. This still doesn't quite work when the directory names contain spaces. I solved this by swapping the second line to sed 's/^/"/g' toremove | sed 's/$/"/g' | xargs rm -r – MikeFHay Dec 31 '12 at 1:27
  • 1
    This will not work on files with spaces. Also will break if the current directory contains a *.rar file due to lack of quoting. – jordanm Dec 31 '12 at 3:28
  • @MikeL: Thanks for the improvement; I replaced the second command with your version. – cpast Dec 31 '12 at 3:39
  • 2
    @MikeL This is good enough for you because Windows filenames can't contain \" or newlines, but in general, this method is unsafe. There's no convenient way to use xargs (except xargs -0) with arbitrary file names. It's usually better to use find -exec. – Gilles 'SO- stop being evil' Jan 1 '13 at 1:14
  • @cpast dirname was a great idea. Thanks. – Jérémie Apr 15 '20 at 15:36

With zsh:

rm -rf **/*.rar(:h)

The suffix :h applies the history expansion modifier h (“head”) which removes the basename of each match, keeping only the directory part.

Make sure to check that these are really the directories you want to delete! For example, move them to a temporary directory first:

mkdir DELETE
mv **/*.rar(:h) DELETE/
# check that you really want to delete everything in DELETE
rm -r DELETE

You can use bash -c to perform more advanced operations in and -exec for find. The problem with using a temp file and cat in combination with xargs is that it will break if a file contains a space, newline, or tab. The following should work:

find . -type f -name '*.rar' -exec bash -c 'rm -rf "${@%/*}"' -- {} +

Using + for find with "$@" will execute rm one time like with xargs.


Bash 4+ solution:

shopt -s globstar
for f in ./**/*.rar; do rm -rf "${f%/*}"; done

You could try something like this:

for dir in */; do             # iterate all subdirectories
    touch $dir"dummy.rar"     # create a "rar"-file...
    for file in $dir*.rar; do # ...so this won't break on zero such
        rm $file              # remove the dummy, and all archives
  • OK, I read @cpast's answer and I see now that you want to remove the subdirectories, not the just the archives. My mistake! (But, isn't that a bit strange behavior?) – Emanuel Berg Jan 1 '13 at 1:32

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.