Reputation: 4641
I have a directory with several subdirs which contain .flac
files. I want to batch convert them to .mp3
. The path names contain spaces. Now I want to do something like this
find . -type f -regex .*.flac -exec ffmpeg -i {} -c:a mp3 -b:a 320k \;
But the question is, how can I use {}
and substitute flac
for mp3
to give ffmpeg an output file name? In bash, one could use variable substitution ${file%.flac}.mp3
, but I cannot apply this here. sed
-based approaches don't seem to work with find
either.
Is there any simple solution to this?
Upvotes: 2
Views: 375
Reputation: 46903
If you really want to use find
(e.g., you're stuck in the past with an antique version of Bash and globstar
isn't available — so using Tom Fenech's solution is not an option), you have to spawn a shell to do the substitution. The standard way would be:
find . -name '*.flac' -type f -exec sh -c 'ffmpeg -i "$1" -c:a mp3 -b:a 320k "${1%.flac}.mp3"' dummy {} \;
sh -c
will run its first argument, and the subsequence arguments are set to the positional parameters starting from 0
. That's why I put a dummy parameter (and I called it dummy
, but anything else could do).
Note that in find
's -name
, the argument *.flac
needs to be quoted. For some reason you edited your post and replaced the -name
predicate with a -regex
predicate: it's really useless, and you still need to quote the argument anyways.
Upvotes: 2
Reputation: 74695
If you're using bash, I'd use globstar
, which will expand to the list of all your .flac
files:
shopt -s globstar nullglob
for file in **/*.flac; do
[[ -f $file ]] || continue
out_file=${file%.flac}.mp3
ffmpeg # your options here, using "$out_file"
done
The check [[ -f $file ]]
skips any directories that end in .flac
. You could probably skip this if you don't have any of those.
I've also enabled the nullglob
shell option, so that a pattern which doesn't match any files expands to nothing (so the loop won't run).
Upvotes: 4