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):

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?

  • 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, 2009 at 22:19

3 Answers 3


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

IFS=$(echo -en "\n\b")
for dir in $(find . -type d)
        mp3gain $dir/*

as a single command:

OLDIFS=$IFS;IFS=$(echo -en "\n\b");for dir in $(find . -type d);do mp3gain $dir/*;done;IFS=$OLDIFS
  • 2
    will this handle spaces-in-dir-names properly? i've never managed to get the bash for loop to NOT split on spaces. Nov 29, 2009 at 20:56
  • good call. fixed!
    – John T
    Nov 29, 2009 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. Nov 29, 2009 at 21:19
  • You should be able to do IFS=$'\n\b' Nov 29, 2009 at 22:36
  • @~quack: There's no need to export those variables. Nov 29, 2009 at 22:43

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
  • 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, 2009 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, 2009 at 22:05

You can use Rebol it works on Unix and Windows

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


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .