Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When reading a file line by line, I only get to execute ffmpeg on the first line

Tags:

bash

video

ffmpeg

I'm writing a Bash script in which I read a file line by line ( well, <(find /home/user/ -iname "*.MP4") to be exact ) , and for each line I execute ffmpeg, so I'm doing something like this:

while read -r line; do
    ffmpeg -i "$line" [ MORE OPTIONS ... ]
done < <(find /home/user/ -iname "*.MP4")

Though, for some reason, only the first line is being processed successfuly.

Any idea why my code ignores all other lines ?

like image 956
Shmuel Avatar asked Apr 12 '16 21:04

Shmuel


1 Answers

That's a frequent problem which is caused by the special behavior of ffmpeg (also happens with ssh ).

Quoted from Bash FAQ 89 which handles your case almost exactly:

What's happening here? Let's take the first example. read reads a line from standard input (FD 0), puts it in the file parameter, and then ffmpeg is executed. Like any program you execute from BASH, ffmpeg inherits standard input, which for some reason it reads. I don't know why. But in any case, when ffmpeg reads stdin, it sucks up all the input from the find command, starving the loop.

TL;DR :

There are two main options:

  • Adding a </dev/null at the end of ffmpeg's line ( i.e. ffmpeg -i "$line" [ MORE OPTIONS ] ... </dev/null ) will fix the issue and will make ffmpeg behave as expected.

  • Let read read from a File Descriptor which is unlikely to be used by a random program:

       while IFS= read -r line <&3; do
           # Here read is reading from FD 3, to which 'file' is redirected.
       done 3<file
    
like image 185
Rany Albeg Wein Avatar answered Sep 23 '22 10:09

Rany Albeg Wein