如何继续嵌套 for 循环并出现“zsh:未找到匹配项”错误?

如何继续嵌套 for 循环并出现“zsh:未找到匹配项”错误?

我有许多按日期、摄像机频道、事件时间范围划分的视频文件 ( 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

我想仅按日和摄像机频道合并这些剪辑(即/2021-04-03-CH1.mp4

我的流程是:

  1. 遍历每个日期文件夹 ( for VIDEODIR in */)
  2. 在每个文件夹中,迭代每个通道号 ( for VIDEOCHANNELNUMBER in 1 2 3 4 5 6; do)
  3. 对于每个频道号,找到要合并的所有视频文件 ( for f in $VIDEODIR/ch$VIDEOCHANNELNUMBER*.mp4 ; do)
  4. FFMPEG 合并并将该文件保存到根目录( ffmpeg -i $VIDEOLIST -c copy "$DATE-CH$VIDEOCHANNELNUMBER.mp4")
  5. 成功后删除所有原始剪辑的目录。 ( if [ $? -eq 0 ]; then rm $VIDEODIR -r fi)

我陷入了困境,因为当由于某种原因该视频频道在当天离线而没有匹配项时,第 2 步会出错。 ( zsh: no matches found: /2021-07-03/ch1*.mp4)。这会打破整个循环,而不是跳过并继续。

答案1

您可以使用Nglob 限定符来表示您希望 glob 扩展为空,而不是在没有匹配项时返回错误,并使用限定符/来选择目录类型的文件。

N在分配给数组变量时,您通常需要使用限定符:

dirs=( *(N/) )

或循环时:

for dir in *(N/)

所以,我不太清楚你想做什么,但这可能看起来像:

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

在这里,您可以采取不同的方法来一次循环所有文件:

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]} 

(并rmdir <1900-2100>-<1-12>-<1-31>(/^F)随后删除空目录)。


有趣的是,这就是它的作用fish:当没有像 in 那样的匹配时,它的 glob 会出错,zsh除非 glob 与for, set(分配给变量)或 一起使用count

相关内容