How to skip if file not found in bash?

Hello,
I have a question regarding while loop and existence of files.
I am running under ubuntu 18.04 bionic, have around fifty video files inside the directory.

script:

for file in *.mp4
do
/root/bin/ffmpeg -i $file \
-i $(basename "${file/.mp4}").bs.srt \
-i $(basename "${file/.mp4}").da.srt \
-i $(basename "${file/.mp4}").slo.srt \
-i $(basename "${file/.mp4}").sv.srt \
-map 0:v -map 0:a \
-map 1 -map 2 -map 3 -map 4 \
-c:v copy -c:a copy -c:s copy  -metadata:s:s:0 \
language=bos -metadata:s:s:1 language=dan -metadata:s:s:2 
language=slo -metadata:s:s:3 language=swe "${file/.mp4}")_output.mp4
done

What I wish to do is to prevent receiving "srt file not found" error in case there is no searched srt files inside the directory. If I don't do that, process fails.

For example,

File1.mp4 -> I have only File1.bs.srt and File1.da.srt
File2.mp4 -> I have only File2.slo.srt and File2.sv.srt

When File1.mp4 is in use, it will just take File1.bs.srt and File1.da.srt, and will skip File1.slo.srt and File1.sv.srt

How may I accomplish this?

Thanks in advance
Boris

Hmmm - not that simple. Would ffmpeg accept reading from /dev/null (to substitute a non-existing .srt file)?

And, you don't need the basename for files in your working directory.
And, you could use "brace expansion" to have the shell create the include file list:

echo /root/bin/ffmpeg -i $file -i\ ${file/.mp4}.{bs,da,slo,sv}.srt
/root/bin/ffmpeg -i FILE3.mp4 -i FILE3.bs.srt -i FILE3.da.srt -i FILE3.slo.srt -i FILE3.sv.srt

Dear Rudic,
If you have any recommendations I would try at my end.
I thought that if I can store each mp4 file and related srt files in the same directory (I mean fifty different directories, for file1 only file1.mp4 and related srt files, for file2 a new directory with related srt files etc.. ), I may list all files and store in a new file and then echo what I need. A bit complicated I think.

ls -a > file_list
for file in *.srt
do
echo "ffmpeg ..."
done > edit.sh
chmod 755 edit.sh
./edit.sh

By the way, Scrutinizer gave a reply but I can not see his post under the same thread..

Thanks
Baris

Should ffmpeg not complain if asked to include /dev/null , try

for file in *.mp4
   do   FN=($(ls "${file/.mp4}"*.srt))
        echo /root/bin/ffmpeg -i $file -i ${FN[0]:-/dev/null} -i ${FN[1]:-/dev/null} -i ${FN[2]:-/dev/null} -i ${FN[3]:-/dev/null}
   done
/root/bin/ffmpeg -i FILE1.mp4 -i FILE1.da.srt -i FILE1.slo.srt -i /dev/null -i /dev/null
/root/bin/ffmpeg -i FILE2.mp4 -i FILE2.bs.srt -i FILE2.da.srt -i FILE2.slo.srt -i FILE2.sv.srt
/root/bin/ffmpeg -i FILE3.mp4 -i FILE3.bs.srt -i FILE3.da.srt -i FILE3.sv.srt -i /dev/null
1 Like

Thank you million times Rudic,
Gives the expected output.

Kind regards
Boris

Well, well... how about this one:

for file in *.mp4
  do    echo /root/bin/ffmpeg -i $file $(printf -- "-i %s "  $(ls "${file/.mp4}"*.srt))
  done
/root/bin/ffmpeg -i FILE1.mp4 -i FILE1.da.srt -i FILE1.slo.srt
/root/bin/ffmpeg -i FILE2.mp4 -i FILE2.bs.srt -i FILE2.da.srt -i FILE2.slo.srt -i FILE2.sv.srt
/root/bin/ffmpeg -i FILE3.mp4 -i FILE3.bs.srt -i FILE3.da.srt -i FILE3.sv.srt
1 Like

The only problem regarding your first solution is that we can not grab the "language" field. I will test the second one when I show up to my house. On my way to home...

Why shouldn't you be able to "grab the "language" field"?

As per your question, I have to edit the script as follows, that was my fault.
I should have mentioned that language field has relation with srt field.

for file in *.mp4
do
/root/bin/ffmpeg -i $file \
-i $(basename "${file/.mp4}").bos.srt \
-i $(basename "${file/.mp4}").dan.srt \
-i $(basename "${file/.mp4}").slo.srt \
-i $(basename "${file/.mp4}").swe.srt \
-map 0:v -map 0:a \
-map 1 -map 2 -map 3 -map 4 \
-c:v copy -c:a copy -c:s copy  -metadata:s:s:0 \
language=bos -metadata:s:s:i language=dan -metadata:s:s:(i+) 
language=slo -metadata:s:s:(i++) language=swe "${file/.mp4}")_output.mp4
done

tag of srt extension refers to language. If it finds *.bos.srt, it will put language=bos , bosnian language etc.
if it finds slo.srt, language should be language=slo etc.. Metadata nr increases as more srt file is found as it goes.

I am sorry again

So it is different from what you posted first?

No, not much... Language names are variable and connected to found srt files but not a big problem Rudic. Thank you so much for your support. I will find a way to sort the last part.

Kind regards
Boris

Given the language code is the same in filenames and the metadata specification, try

for file in *.mp4
  do    printf -vINCLUDE -- "-i %s "  ${file/.mp4}*.srt
        T1=( ${INCLUDE//-i} )
        T2=( ${T1[@]%.*} )
        for (( i=0; i<${#T2[@]};i++)) do        ML=$ML" -metadata:s:s:$i language=${T2#*.}"
                                                MP=$MP" -map $((i+1))"
                                       done
        echo /root/bin/ffmpeg -i $file "$INCLUDE" "$MP" "$ML"
        unset ML MP INCLUDE T1 T2
  done
/root/bin/ffmpeg -i FILE1.mp4 -i FILE1.dan.srt -i FILE1.slo.srt  -map 1  -map 2   -metadata:s:s:0 language=dan -metadata:s:s:1 language=slo
/root/bin/ffmpeg -i FILE2.mp4 -i FILE2.bos.srt -i FILE2.dan.srt -i  FILE2.slo.srt -i FILE2.swe.srt  -map 1 -map 2 -map 3 -map 4    -metadata:s:s:0 language=bos -metadata:s:s:1 language=dan  -metadata:s:s:2 language=slo -metadata:s:s:3 language=swe
/root/bin/ffmpeg -i FILE3.mp4 -i FILE3.bos.srt -i FILE3.dan.srt -i  FILE3.swe.srt  -map 1 -map 2 -map 3   -metadata:s:s:0 language=bos  -metadata:s:s:1 language=dan -metadata:s:s:2 language=swe
1 Like

Dear Rudic,
All ok now. I put space between map and $ sign in here, (as you did also) :

MP=$MP" -map $((i+1))"

Then, I had to change below part as language info was not giving the same result with yours:

language=${T2#*.}"

to:

language=${T2#.}"

Thank you so much again.

Kind regards
Boris