34

I have three .wav files in my folder and I want to convert them into .mp3 with ffmpeg.

I wrote this bash script, but when I execute it, only the first one is converted to mp3.

What should I do to make script keep going through my files?

This is the script:

#!/bin/bash
find . -name '*.wav' | while read f; do
    ffmpeg -i "$f" -ab 320k -ac 2 "${f%.*}.mp3"
done
0

3 Answers 3

84
+50

Use the -nostdin flag to disable interactive mode,

ffmpeg -nostdin -i "$f" -ab 320k -ac 2 "${f%.*}.mp3"

or have ffmpeg read its input from the controlling terminal instead of stdin.

ffmpeg -i "$f" -ab 320k -ac 2 "${f%.*}.mp3" </dev/tty

See the -stdin/-nostdin flags in the ffmpeg documentation, as well as the FAQ How do I run ffmpeg as a background task?.

Sign up to request clarification or add additional context in comments.

Comments

21

If you do need find (for looking in subdirectories or performing more advanced filtering), try this:

find ./ -name "*.wav" -exec sh -c 'ffmpeg -i "$1" -ab 320k -ac 2 "$(basename "$1" wav).mp3"' _ {} \;

Piping the output of find to the while loop has two drawbacks:

  1. It fails in the (probably rare) situation where a matched filename contains a newline character.
  2. ffmpeg, for some reason unknown to me, will read from standard input, which interferes with the read command. This is easy to fix, by simply redirecting standard input from /dev/null, i.e. find ... | while read f; do ffmpeg ... < /dev/null; done.

In any case, don't store commands in variable names and evaluate them using eval. It's dangerous and a bad habit to get into. Use a shell function if you really need to factor out the actual command line.

1 Comment

Thanks, it is my prefered answer that is elegant in only one line… here are my rewrite to compress smartphone mp4 : find ./ -name "2024071[78]_1[56]*.mp4" -exec sh -c 'ffmpeg -i "$1" -s wvga -vcodec libx264 "$(basename "$1"-red).mp4"' _ {} \;
3

No reason for , just use wildcard globbing

#!/bin/bash
for name in *.wav; do
  ffmpeg -i "$name" -ab 320k -ac 2 "${name%.*}.mp3" 
done 

3 Comments

That will not handle subdirectories.
Downvoted. This is a workaround that explains bash features, not a solution to the actual problem with ffmpeg. See Shammell Lee's answer.
There are possible throws if no pause in loop(as to me) so this one is working too avoiding throws: #!/bin/bash FILES="/path/*.mp4" for f in $FILES do echo "------Processing $f VIDEO..." sudo ffmpeg -i "$f" -vn -ar 44100 -ac 2 -ab 192K -f mp3 "$f.mp3" echo "======Processed to $f.mp3" read -t 3 -p "Pause 3 sec ..." done . put it as sh script chmod +x this_script.sh and sudo ./this_script.sh

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.