Bash 遍历输出不存在文件的目录中的文件

Bash loop over files in directory outputting non existent files

我正在用一系列图像制作 mp4 文件。图片应该 运行 大约 1 小时,但我无法获得完整的视频,因为 FFMPEG 寻找它不应该拥有的文件。

[image2 @ 0x55fe14bef700] Could not open file : /mnt/run/image-005437.jpeg

令人困惑的是,我传递给 ffmpeg 的列表应该 不包括该文件。如果我的脚本不喜欢结果,它会将文件发送到目标文件夹中名为 failed

的子目录

具有该编号的文件的位置

$ pwd
run/failed
]$ ls
failed-005437.jpeg 

我用来启动 ffmpeg 的命令如下

image_folder=
singularity exec --bind $work_dir:/mnt $work_dir/longleaf2.sif ffmpeg -f concat -safe 0 -y -i <(for f in /mnt/processed_images/$image_folder/image-%06d.jpeg; do echo "file '$f'";done) -vf "crop=trunc(iw/3)*2:trunc(ih/2)*2" -movflags +faststart /mnt/run/summary_files/${image_folder}.mp4

我已经检查过处理过的图像,但它不在那里,为什么 ffmpeg 正在寻找它?

失败的运行

的pastebin

https://pastebin.com/pF5ZefLf

我检查该文件不在 for 循环引用的文件夹中,因此它永远不会导致错误

$ ls image-005437.*
ls: cannot access image-005437.*: No such file or directory

问题

当你 运行:

for f in /mnt/processed_images/$image_folder/image-%06d.jpeg; do echo "file '$f'";done

它将输出:

file '/mnt/processed_images/foo/image-%06d.jpeg'

那么 ffmpeg 将使用 image demuxer 的序列模式类型。这需要一个连续的序列。

解决方案 1:Glob

使用 glob:

for f in /mnt/processed_images/$image_folder/*.jpeg; do echo "file '$f'";done

现在它将输出每个文件。在此示例中 image-000003.jpeg 不存在,因此未列出:

file '/mnt/processed_images/foo/image-000001.jpeg'
file '/mnt/processed_images/foo/image-000002.jpeg'
file '/mnt/processed_images/foo/image-000004.jpeg'

解决方案 2:简化并跳过 concat

更好的是通过在 ffmpeg 本身中使用 image demuxer 的 glob 模式类型来简化您的命令,然后您可以避免 concat demuxer:

image_folder=
singularity exec --bind "$work_dir":/mnt "$work_dir"/longleaf2.sif ffmpeg -pattern_type glob -framerate 25 -i "/mnt/processed_images/$image_folder/*.jpeg" -vf "crop=trunc(iw/3)*2:trunc(ih/2)*2,format=yuv420p" -movflags +faststart /mnt/run/summary_files/${image_folder}.mp4
  • Windows 用户无法使用图像分离器 glob 模式。
  • image demuxer 添加了 -framerate 输入选项。
  • 添加了 format filter 以实现 YUV 4:2:0 色度子采样以实现兼容性。
  • 已引用变量。参见 shellcheck.net
  • FFmpeg 4.1 发布分支是旧的。 Download or compile 做任何事情之前的现代版本。