Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I want to apply replaygain information to all the MP3 files in my music collection. To do this, I'm using a tool called mp3gain (on Linux).

In order to apply the album gain correctly, I need to run the mp3gain command on a per directory basis. In other words, I need to find a directory, run mp3gain on all files in that directory, then repeat for every other directory. So far, I've come up with this:

 find . -type d -exec mp3gain {}/*.mp3 \;

The output looks like this (only showing a couple of the many directories):

[...]
./dev2/Physicist/*.mp3
Can't open ./dev2/Physicist/*.mp3 for reading
./Real Things/*.mp3
Can't open ./Real Things/*.mp3 for reading

It appears to me that the '*' is being escaped, so rather than looking for all files ending in '.mp3', it is looking for a file called '*.mp3'.

What command should I use?

share|improve this question
    
Both John T and michaelwells posted solutions that work fine, but I marked John T's solution as correct because he answered first. Thanks all. –  NickG Nov 29 '09 at 22:19
add comment

3 Answers 3

up vote 7 down vote accepted

Looks like it's not globbing properly. How about something like this:

#!/bin/bash
OLDIFS=$IFS
IFS=$(echo -en "\n\b")
for dir in $(find . -type d)
do
        mp3gain $dir/*
done
IFS=$OLDIFS

as a single command:

OLDIFS=$IFS;IFS=$(echo -en "\n\b");for dir in $(find . -type d);do mp3gain $dir/*;done;IFS=$OLDIFS
share|improve this answer
2  
will this handle spaces-in-dir-names properly? i've never managed to get the bash for loop to NOT split on spaces. –  quack quixote Nov 29 '09 at 20:56
    
good call. fixed! –  John T Nov 29 '09 at 21:11
    
+1, nice solution. i think the 1-liner needs to export those variables (assuming bash is the shell) but otherwise that looks right. –  quack quixote Nov 29 '09 at 21:19
    
You should be able to do IFS=$'\n\b' –  Dennis Williamson Nov 29 '09 at 22:36
    
@~quack: There's no need to export those variables. –  Dennis Williamson Nov 29 '09 at 22:43
show 2 more comments

It might not look nice, but this command will find all directories that contain mp3 files write them to a tempfile and then go through that tempfile listing the contents of each dir. If you're happy with the Output, you can go ahead and plug your mp3gain command into it in place of the ls.

Setting the IFS variable to a newline character is important so that you can work with files and directories that contain spaces.

The reason I've chosen to list directories containing mp3s first is in case mp3gain throws an error when encountering empty sets of files. In this way it never encounters such a situation.

IFS=$'\n'; for i in `find -type f -iname *.mp3`; do dirname $i ; done | sort | uniq > ~/mp3directories.txt && for i in `cat ~/mp3directories.txt`; do ls -1 $i/*.mp3 ; echo ; done
share|improve this answer
    
The only issue with this is that he wants to do it 1 directory at a time. If the file names are sorted, it will be grabbing them from all different directories rather than processing each file in one directory then moving onto the next. –  John T Nov 29 '09 at 21:40
    
First, thank you both for taking the time to answer. John T, michaelwells' code spits out a list of directories, not file names. I've tested it and it does what I wanted, albeit only on directories containing MP3s. –  NickG Nov 29 '09 at 22:05
add comment

You can use Rebol it works on Unix and Windows

How to apply a function to all files in a directory recursively

http://reboltutorial.com/blog/how-to-apply-a-function-to-all-files-in-a-directory-recursively/

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