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
我检查该文件不在 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 做任何事情之前的现代版本。
我正在用一系列图像制作 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我检查该文件不在 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 做任何事情之前的现代版本。