When running the following command line to convert multiple .mkv files into .mp4 files, things go awry. It's as if the script tries to run all the commands at once or they get entangled in each other somehow, and the output gets messy. I don't know exactly. When I ran this just now, only the first file was converted. Other times, I seem to get unexpected or random results.

ls -1 *.mkv | while read f; do ffmpeg -i "$f" -codec copy "${f%.*}.mp4"; done

However, if I do the following, things work as expected:

ls -1 *.mkv | while read f; do echo ffmpeg -i \"$f\" -codec copy \"${f%.*}.mp4\"; done > script; bash script

But why? What is it with ffmpeg? This doesn't happen with bash loops and other commands than ffmpeg. I'd like to do it a simple way without escaping quotes, piping to a script file, etc.

  • 3
    Avoid piping ls output, especially to while read. Use the for f in *.mkv; do... construct. Oh, and btw, you don't need -1 when the output is a pipe. Commented Nov 7, 2015 at 21:40
  • 1
    What don_crissti said. Don't parse ls for things like this, especially not media files whose names are very likely to contain strange characters and whitespace. That said, please edit your question and show us this messy output you speak of. What does it look like? We can't help unless you show us the actual problem.
    – terdon
    Commented Nov 7, 2015 at 22:31
  • I had this same problem using something like find . -name "*.aifc" | while read f; do ffmpeg -i $f... -- ffmpeg was stripping characters off of the input filename and I couldn't figure out why! Using the for construct solved the problem.
    – bonh
    Commented Jan 7, 2017 at 17:03

1 Answer 1


ffmpeg reads from standard input as well, consuming data meant for read. Redirect its input from /dev/null:

... | while read f; do ffmpeg -i "$f" -codec copy "${f%.*}.mp4" < /dev/null; done

That said, don't read the output from ls like this. A simple for loop will suffice (and remove the original problem).

for f in *.mkv; do
    ffmpeg -i "$f" -codec copy "${f%.*}.mp4"
  • 1
    Will the prior approach work if using find . -type f (where for won't)?
    – forthrin
    Commented Nov 9, 2015 at 7:50
  • It will; just be aware that file names containing newline characters break that approach.
    – chepner
    Commented Nov 9, 2015 at 11:58
  • Filenames containing newline characters; then I'd say the problem would lie elsewhere :)
    – forthrin
    Commented Nov 10, 2015 at 13:22
  • 1
    No, the problem is with scripts that make naive assumptions about what characters can appear in a file name.
    – chepner
    Commented Nov 10, 2015 at 13:39
  • 1
    This was a tough one to debug -- thanks for saving me a headache today!
    – simon
    Commented Jul 23, 2019 at 2:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .