0

This script has taken me too long (!!) to compile, but I finally have a reasonably nice script which does what I want:

find "$@" -type d -print0 | while IFS= read -r -d $'\0' dir; do
    find "$dir" -iname '*.flac' -maxdepth 1 ! -exec bash -c '
        metaflac --list --block-type=VORBIS_COMMENT "$0" 2>/dev/null | grep -i "REPLAYGAIN_ALBUM_PEAK" &>/dev/null
        exit $?
    ' {} ';' -exec bash -c '
        echo Adding ReplayGain tags to "$0"/\*.flac...
        metaflac --add-replay-gain "${@:1}"
    ' "$dir" {} '+'
done

The purpose is to search the file tree for directories containing FLAC files, test whether any are missing the REPLAYGAIN_ALBUM_PEAK tag, and scan all the files in that directory for ReplayGain if they are missing.

The big stumbling block is that all the FLAC files for a given album must be passed to metaflac as one command, otherwise metaflac doesn't know they're all one album. As you can see, I've achieved this using find ... -exec ... +.

What I'm wondering is if there's a more elegant way to do this. In particular, how can I skip the while loop? Surely this should be unnecessary, because find is already iterating over the directories?

2 Answers2

1

You can probably use xargs to achieve it.

For example, if you are looking for text foo in all your files you'll have something like

find . type f | xargs grep foo

xargs passes each result from left-end expression (find) to the right-end invokated command.

Then, if no command exists to achieve what you want to do, you can always create a function, and pass if to xargs

Thibault D.
  • 10,041
  • 3
  • 25
  • 56
0

I can't comment on the flac commands themselves, but as for the rest:

find . -name '*.flac' \
 ! -exec bash -c 'metaflac --list --block-type=VORBIS_COMMENT "$1" | grep -qi "REPLAYGAIN_ALBUM_PEAK"' -- {} \; \
  -execdir bash -c 'metaflac --add-replay-gain *.flac' \;

You just find the relevant files, and then treat the directory it's in.

that other guy
  • 116,971
  • 11
  • 170
  • 194
  • I looked into this, but it didn't seem to work. The trouble is, `-execdir` works in the same way as `-exec`, but runs the command in each file's directory. So this means `find` will run that command for every file it finds, not just once per directory. Unless you know something I don't? – Alexander Melhuish Feb 18 '13 at 16:17
  • My assumption was that `--add-replay-gain` would add this REPLAYGAIN_ALBUM_PEAK so that further files in the directory wouldn't match. – that other guy Feb 18 '13 at 18:40
  • That's a good point! I thought it was a bit wasteful checking all the files after applying tags, but my original script does that anyway in a different order. Thanks =) – Alexander Melhuish Feb 20 '13 at 07:58