7

My ~/Music/ directory is actually full of "empty" directories I want to clean. I say "empty" because this directories actually contain files, some contain old cover image files or Thumbs.db files.

I want to recursively delete all of these directories that don't contain any music files inside or other directories inside.

For example ~/Music/Audioslave/ contains a lot of directories with album names and no music files, but I don't want to delete it because inside there are the music files. I want though to delete ~/Music/Audioslave/oldalbum/ if the oldalbum directory doesn't have nor music files nor other directories inside.

  • follow-up Q's: (1) Do you have only one folder with many other folders that contain files other than music files? (2) did you mean you have one folder, with folders that contain both folders and files where some folders carry music files and others do not? – slm Nov 1 '13 at 21:58
  • See the solution I provided, it can handle the nested directories issue. – slm Nov 1 '13 at 22:00
  • Your phrasing is still off (at least to me) I think what you're trying to say is you don't want to delete any directories that have mp3 files in them or contain nested directories that contain mp3 files, no? – slm Nov 1 '13 at 22:04
  • that's exactly what I need, but also for .flac and .m4a! – volotec Nov 1 '13 at 22:12
  • the answer I provided gives you this. I'll add those media types to it as well. – slm Nov 1 '13 at 22:17
4

I found this example on SO, titled: Terminal - Delete All Folders Not Conatining .mp3 Files.

#! /bin/bash

find -depth -type d | while read -r D
 do
 v=$(find "$D" -iname '*.mp3')
 case "$v" in
 ""  )
    echo "$D no mp3"
    # rm -fr "$D" #uncomment to use
 ;;
 esac
done

Example

Sample data.

.
|-- 1
|   |-- 1.mp3
|   `-- 1.txt
|-- 2
|   `-- 2.mp3
|-- 3
|   `-- 3.txt
|-- 4
|   `-- 4.txt
|-- 5
|   `-- 5.mp3
|-- 6
|   `-- 61
|       `-- 61.mp3
|-- 7
|   `-- 71
|       `-- 71.txt
`-- deletenomp3.bash

Sample run

If I were to run it it would delete the following:

$ ./deletenomp3.bash 
./7 no mp3
./7/71 no mp3
./4 no mp3
./3 no mp3

Other file types

You can simply extend this by adding more -name arguments to the 2nd find command in the script. Example, to add .wav files:

 v=$(find "$D" -iname '*.mp3' -o -iname '*.wav');

That says *.mp3 OR *.wav. To add more or others:

 v=$(find "$D" -iname '*.mp3' -o -iname '*.flac' -o -iname '*.m4a');

I'm sure this block could be condensed if you had a lot more file types using alternative switching to find.

  • OK, it worked! Thanks a lot for your help. I wanted to give your answer points but since I'm new the system won't let me do it since I lack reputation points :( – volotec Nov 1 '13 at 22:48
  • @volotec - you can mark it as the accepted answer 8-). Once you get over 15 points you can start to upvote. – slm Nov 1 '13 at 22:49
6

A funny solution involves a find inside a find, but in a safer way than the accepted answer (I personally dislike parsing the output of a command, being ls or find, especially with no precautions). The following command will print the folders that don't contain any music file (here, music file means has an extension mp3, flac, ogg, wav or m4a, but feel free to add some more):

find . -depth -type d \! -exec sh -c 'find "$1" \( -iname "*.mp3" -o -iname "*.flac" -o -iname "*.ogg" -o -iname "*.wav" -o -iname "*.m4a" \) -type f | read a' _ {} \; -print

You should try this on your system, when you're happy the way it behaves, replace the final -print with -exec rm -rfv -- {} \;

The way the file names are used here makes this method 100% safe regarding file names with funny symbols (i.e., spaces, quotings, newlines, trailing newlines, leading and trailing spaces, etc.).

  • @volotec - as I indicated in my answer it could be condensed, this is how. – slm Nov 1 '13 at 23:35
0

Try something along the lines of this (untested):

for dir in ~/Music/* ; do
    found=false
    # Add your music file extensions here.
    for file in "$dir"/*.{mp3,wav} */ ; do
        if ls "$file" > /dev/null 2>&1 ; then
            found=true
            break
        fi
    done

    if ! $found ; then
        # Remove 'echo' when you are ready.
        echo rm -vrf "$dir"
    fi
done

I am not sure how many shells support the */ globbing. At least Bash and Zsh do.

  • 1
    The directories are not empty. What he really wants are directories that don't contain '*.mp3' or maybe '*.wav'. – jordanm Nov 1 '13 at 21:34
  • Yes I know. Thing is the directories I want to remove contain certains files that are not music. For example Thumbs.db files. For that reason I can't use the -empty option for find – volotec Nov 1 '13 at 21:34
  • I read the question too quickly and missed the main point. I will write a new answer. – user26112 Nov 1 '13 at 21:35
  • I have replaced my answer. – user26112 Nov 1 '13 at 21:40
  • Actually running your script made me realize my question was incomplete. I'm going to edit it, thanks! – volotec Nov 1 '13 at 21:56

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.