1

I have many video files that are split by Day, Camera Channel, Event time range (YYYY-MM-DD/VIDEOCHANNELNUMBER-EVENTIMERANGE.mp4)

/2021-07-03/ch2_main_20210703074010_20210703074154.mp4
/2021-07-03/ch2_main_20210703074156_20210703074357.mp4
/2021-07-03/ch2_main_20210703074446_20210703074537.mp4
/2021-07-03/ch2_main_20210703074618_20210703075119.mp4
/2021-07-03/ch2_main_20210703075153_20210703075312.mp4
/2021-07-03/ch2_main_20210703075337_20210703080422.mp4

I want to merge these clips by Day and Camera Channel only (ie /2021-04-03-CH1.mp4)

My process is:

  1. Iterate through each date folder (for VIDEODIR in */)
  2. Within each folder, iterate through each channel number (for VIDEOCHANNELNUMBER in 1 2 3 4 5 6; do)
  3. for each channel number, find all the video files to combine (for f in $VIDEODIR/ch$VIDEOCHANNELNUMBER*.mp4 ; do)
  4. FFMPEG combine and save this file into the root directory (ffmpeg -i $VIDEOLIST -c copy "$DATE-CH$VIDEOCHANNELNUMBER.mp4")
  5. When successful delete the directory of all the original clips. (if [ $? -eq 0 ]; then rm $VIDEODIR -r fi)

I'm stuck because Step 2 errors out when there are no matches due to that video channel being offline during that day for some reason. (zsh: no matches found: /2021-07-03/ch1*.mp4). This breaks the entire loop, rather than skip and continue.

1

1 Answer 1

2

You use the N glob qualifier to say that you want a glob to expand to nothing rather than return an error when there's no match, and the / qualifier to select files of type directory.

You typically want to use the N qualifier when assigning to an array variable:

dirs=( *(N/) )

or when looping¹:

for dir in *(N/)

So, I'm not exactly clear as to what you want to do, but that could look like:

for dir in *(N/); do
  for (( channel = 1; channel <= 6; channel++ )); do
    files=( $dir/ch${channel}_*.mp4(N) )
    if (( $#files )); then
      ffmpeg ... $file
    fi
  done
done

Here, you may be able to take a different approach that loops over all the files at once:

typeset -A list=()
for file (<1900-2100>-<1-12>-<1-31>/ch<1-6>_*.mp4(Nn))
  files[$file:h-${${file:t}%%_*}.mp4]+=$file$'\0'

for output_file (${(k)list})
  ffmpeg -i ${(0)list[$output_file]} -c copy $output_file &&
    rm -f ${(0)list[$output_file]} 

(and rmdir <1900-2100>-<1-12>-<1-31>(/^F) to remove the empty dirs afterwards).


¹ Anecdotally, that's what the fish does: its globs error out when there's no match like in zsh except when the globs are used with for, set (to assign to variables) or count.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.