views:

106

answers:

3

Hi, I'm using Banshee on Linux and I have it auto-organize my music collection in folder hierarchies. When I add a new album to my Music folder, Banshee automatically moves (and renames) the mp3s and puts them into the correct Artist folder. If there is no other file in the folder, then the folder is also deleted, but if other files are present, only the mp3s are moved and the folder remains. Because of this, I have a number of folders inside my music folder that contain no mp3s, only an image file or similar ancillary file.

How would I go about removing any folder (inside the Music folder) that does not have an mp3 file inside?

For example, suppose I have the following:

/home/user/Music/

and I add the folder "Album 1 (2010)" which has mp3s and also cover art. Banshee will pull out the mp3s and put them in the proper artist folder, say:

/home/user/Music/Artist

but then the folder

/home/user/Music/Album 1 (2010)

still exists. How can I check if this folder has an mp3 in it, and if not, delete it?

I figure the answer will be a command line one, but I'm open to any suggestion. Also, it might be good to require a confirmation...just in case.

Thanks!

+1  A: 
#! /bin/bash

shopt -s nullglob
shopt -s nocaseglob
find -depth  -type d | { while read -r D;
 do
 case "$D" in
    "$DR" ) continue;;
 esac
 v=$(echo "$D"/*.mp3)
 case "$v" in
 ""  )
    echo "$D no mp3, to be deleted";;
    # rm -fr "$D" #uncomment to use
 *)
     DR=${D%/*}
     ;;
 esac
done }
ghostdog74
This gives me a list of all directories containing no mp3 file. An unexpected problem, however, is that each artist folder has no mp3s itself. I ran the code to just echo the directories and just manually deleted the relatively small number of directories. Otherwise, I think I might have deleted the top level artist directories (which contain the album directories inside).
John Smith
Wait...this doesn't work for folder with a space in them...let me play around with quotation marks.
John Smith
put quotes then. I left it out earlier.
ghostdog74
This finds my simon_and_garfunkel directory, which has no MP3s in it, but does have MP3s in its subfolders.
Ken Bloom
To find bottom up, you can use the `-depth` option. see my edit.
ghostdog74
I've now edited to fix my problem. (Not sure if the `-depth` option was supposed to help with that or not. I didn't test it.)
Ken Bloom
@Ken, why are you editing my post adding another layer of redundancy and without testing ?
ghostdog74
@ghostdog74: because I was testing it simultaneously with your addition of `-depth`. And now that I just tested, it doesn't work without the second `find` command.
Ken Bloom
@Ken, if you put a second `find` without a `maxdepth`, its going to traverse the directory again.! And there's no need to have a 2nd `find`. please don't edit the post any more. I would rather edit it myself after OP tell me his problems after using it.
ghostdog74
@ghostdog74 `mkdir -p test/deleteme test/save test/save-recursive/nested; touch test/save/x.mp3 test/save-recursive/nested/x.mp3; cd test`. Now run the various versions of this script from inside the `test` directory. Your version will ask to delete `./deleteme`, `./save-recursive`, and `.`.
Ken Bloom
Since ghostdog74 objcets to my edits, and won't fix this himself, the proper solution is to use `find "$D" -name '*.mp3'` instead of `echo "$D"/*.mp3`.
Ken Bloom
+1  A: 

Can't comment yet, but @ghostdog74 's find command checks the current directory for mp3s in addition to the actual subdirectories, if there are no mp3s loose in /home/user/Music, it'll remove the whole tree.

If these are completely empty directories, then rmdir * will do the trick without any scripting needed: rmdir can't remove files or directories with files in them.

For dealing with spaces, run IFS=$(echo -en "\b\n") either at the top of the command or in the shell first. This prevents variables from expanding into multiple arguments when the variable contains a space. If you do this in the shell, you'll probably want to do something like SAVEIFS=$IFS; IFS=...; do stuff; IFS=$SAVEIFS so that you can get the original setting back, or just close the terminal and open a new one to get a fresh environment.

DerfK
This is more appopriate as a comment on ghostdog74's answer.
Ken Bloom
A: 

Based on ghostdog74's answer:

#! /bin/bash

find -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 }

Let's test it on the directory structure

.
./deleteme
./save2
./save2/x.MP3
./save-recursive
./save-recursive/nested
./save-recursive/nested/x.mp3
./save
./save/x.mp3

The output is:

./deleteme no mp3
Ken Bloom
This is the magic answer, I believe. It also helped me realize that I have some files with .MP3 as the extension rather than .mp3. This script shows all those and also the non-mp3 files I am looking for.
John Smith
Oh, you probably want `-iname` then to match the case-insensitive names. I've edited to include that. The various glob options in the shell should be irrelevant, since there are no actual globs being performed by the shell, so I've removed those.
Ken Bloom
thank you ghostdog and Ken for the minor edits.
John Smith
yeah, the -iname switch solves the capital MP3 extension problem. And I've seen the glob options before, better go google them...
John Smith