Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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 for help after almost deleting stuff I didn't mean to.

I'm using Cygwin on Windows 7, in case that's relevant.

share|improve this question
add comment

5 Answers 5

up vote 1 down vote accepted

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.

share|improve this answer
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 Jan 1 '13 at 1:14
add comment

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
share|improve this answer
add comment

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.

share|improve this answer
add comment

Bash 4+ solution:

shopt -s globstar
for f in ./**/*.rar; do rm -rf "${f%/*}"; done
share|improve this answer
add comment

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
    done
done
share|improve this answer
    
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
add comment

Your Answer

 
discard

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.