This is on Ubuntu 12.04 I'm trying to figure out how to get ffmpeg to do a batch conversion of FLACs to MP3, recursively. If I cd
into a directory and use
for f in *.flac; do ffmpeg -i "$f" -c:a libmp3lame -q:a 2 "${f/%flac/mp3}"; done
that works perfectly fine. However, when I try this, it doesn't work:
for f in "$(find . -type f -name *.flac)"; do ffmpeg -i "$f" -c:a libmp3lame -q:a 2 "${f/%flac/mp3}"; done
It doesn't even throw up any useful errors (but here is the output anyway, no need to complain):
evilsoup@enchantment:~/Music/Jean Sibelius$ for f in "$(find . -type f -name *.flac)"; do ffmpeg -i "$f" -c:a libmp3lame -q:a 2 "${f/%flac/mp3}"; done
ffmpeg version git-2012-12-18-b7e085a Copyright (c) 2000-2012 the FFmpeg developers
built on Dec 18 2012 19:23:11 with gcc 4.6 (Ubuntu/Linaro 4.6.3-1ubuntu5)
configuration: --enable-gpl --enable-libfaac --enable-libfdk-aac --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-librtmp --enable-libtheora --enable-libvorbis --enable-libvpx --enable-x11grab --enable-libx264 --enable-nonfree --enable-version3
libavutil 52. 12.100 / 52. 12.100
libavcodec 54. 80.100 / 54. 80.100
libavformat 54. 49.102 / 54. 49.102
libavdevice 54. 3.102 / 54. 3.102
libavfilter 3. 28.100 / 3. 28.100
libswscale 2. 1.103 / 2. 1.103
libswresample 0. 17.102 / 0. 17.102
libpostproc 52. 2.100 / 52. 2.100
./Symphonies 1, 2, 3 & 5 (Oslo Philharmonic Orchestra Conducted by Mariss Jansons) Disc 1/02. Symphony No.1.flac
./Symphonies 1, 2, 3 & 5 (Oslo Philharmonic Orchestra Conducted by Mariss Jansons) Disc 1/03. Symphony No.1.flac
./Symphonies 1, 2, 3 & 5 (Oslo Philharmonic Orchestra Conducted by Mariss Jansons) Disc 1/stripped2.flac
./Symphonies 1, 2, 3 & 5 (Oslo Philharmonic Orchestra Conducted by Mariss Jansons) Disc 1/05. Symphony No.1.flac
./Symphonies 1, 2, 3 & 5 (Oslo Philharmonic Orchestra Conducted by Mariss Jansons) Disc 1/stripped3.flac
./Symphonies 1, 2, 3 & 5 (Oslo Philharmonic Orchestra Conducted by Mariss Jansons) Disc 1/09. Andante festivo.flac
./Symphonies 1, 2, 3 & 5 (Oslo Philharmonic Orchestra Conducted by Mariss Jansons) Disc 1/08. Symphony No.3.flac
./Symphonies 1, 2, 3 & 5 (Oslo Philharmonic Orchestra Conducted by Mariss Jansons) Disc 1/01. Finlandia.flac
./Symphonies 1, 2, 3 & 5 (Oslo Philharmonic Orchestra Conducted by Mariss Jansons) Disc 1/07. Symphony No.3.flac
./Symphonies 1, 2, 3 & 5
I've tested the find
command on its own, and it works as expected, so the problem has to be something to do with the interaction between find
and for
.
I'm aware that I could do something with find
's -exec
option, but I can't find any way to do string substitution as I can with a bash for
loop, and I'd rather not have a bunch of file.flac.mp3
s to deal with, even if they could be fixed with a simple rename
.
Answer
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 IFSThe command
unset IFS
changes the IFS back to it's default value (not needed inside a shell script, unless it interferes with subsequent commands).
No comments:
Post a Comment