Why doesn't this for loop work?
Solution 1:
The double quotes around the $(find ...)
command make for see find's output as one single filename, which obviously is not what you want.
There are several ways to achieve what you want:
-
Make find execute ffmpeg directly (no piping, no loops):
find . -type f -name *.flac -exec bash -c ' ffmpeg -i "$0" -c:a libmp3lame -q:a 2 "${0/%flac/mp3}" ' {} \;
-
Use
find ... -print0 | xargs -0 ...
instead of for, which is specifically made for these purposes:find . -type f -name *.flac -print0 | xargs -0 -I {} bash -c ' ffmpeg -i "$0" -c:a libmp3lame -q:a 2 "${0/%flac/mp3}" ' {}
-
Change IFS to newline only, the use the same command as before, minus the double quotes:
IFS=$'\n' for f in $(find . -type f -name *.flac); do ffmpeg -i "$f" -c:a libmp3lame -q:a 2 "${f/%flac/mp3}" done unset IFS
The command
unset IFS
changes the IFS back to it's default value (not needed inside a shell script, unless it interferes with subsequent commands).
Solution 2:
Please read BashFAQ/020 - Greg's Wiki. To properly iterate over the output of find
, here's a method that should cope with all sorts of strange characters in filenames (spaces, newlines, globbing, etc.)
while IFS= read -r -d '' file; do
ffmpeg -i "$f" -c:a libmp3lame -q:a 2 "${f/%flac/mp3}"
done < <(find . -type f -name "*.flac" -print0)
Don't forget to quote "*.flac"
to prevent expansion if there are files in the current directory ending with .flac
.