This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the bash category.
Last Updated: 2023-03-28
I had some code to split a large mp3 (all.mp3). It read from a csv file like the following:
Rorate-coeli,00:00,01:46 Universi-qui-te-expectant,01:46,03:46 Ad-te-levavi,03:47,06:01 Ex-Sion,06:02,07:51.7
Here's the code:
# Notice here, BTW, how IFS is set to `,` (comma) for just this loop, and how # `read` accepts multiple variables, corresponding to the splits on each line while IFS=, read -r name start_t end_t do output_file="./output/$name.mp3" ffmpeg -i all.mp3 -n -acodec copy -ss "00:$start_t" -to "00:$end_t" -f mp3 "$output_file" done < splits.csv
Read will read a line of input into name name1 name2 ... splitting the line based on the contents of the Internal Field Separator (IFS)
When I ran the script, the first few tracks had normal file names, but the later ones had characters loped off the front (e.g. "Ad-te-levavi" might become "e-levavi")
Yet when I simply echoed the variables without
ffmpeg, everything was fine
while IFS=, read -r name start_t end_t do echo $name echo $start_t echo $end_t done < splits.csv
So ffmpeg was somehow messing with the variables.
It transpired that
ffmpeg reads from STDIN — which was "splits.csv" in this
case due to the redirection — and its consumption of input was competing with the
read -r consumption of input in the outer loop.
$ ffmpeg -nostdin ...
while IFS=, read -r name start_t end_t # new bit at end ffmpeg -i all.mp3 -n -acodec copy -ss "00:$start_t" -to "00:$end_t" -f mp3 "$output_file" < /dev/null done < splits.csv
while IFS=, read -r name start_t end_t <&3; do # Here read is reading from FD 3, to which 'splits.csv' is redirected. done 3<splits.csv