提取文件名以命名其他文件时出错

Error when extracting a filename to name other files

我正在尝试使用 FFmpeg 将视频转换为 Bash 中的图像。我想使用视频的文件名来命名相应的图像(后跟一个整数)。

如果我在同一目录中导出文件,我能够做到这一点:

for file in `find . -name "*.mp4"`; do ffmpeg -i $file -q 1 $file'_'%d.jpeg; done

但是,如果我要将图像导出到所需的目录,则会出现错误。看来 $file 的值不仅仅是文件名,而是一个目录。

我在尝试什么:

for file in `find . -name "*.mp4"`; do ffmpeg -i $file -q 1 ~/testfolder/$file'_'%d.jpeg; done

我的问题是:我怎样才能正确提取要在此处使用的文件名?

bash命令basename可用于此。

在这种情况下,下面应该只列出文件:

for file in $(find . -name "*.mp4"); do echo $(basename $file); done

您可以在原始代码中使用 $(basename $file) 来仅获取文件名。

for file in $(find . -name "*.mp4"); do 
  ffmpeg -i "${file}" -q 1 "~/testfolder/$(basename $file)'_'%d.jpeg"
done

这样做,因为它可以处理包含任何特殊字符(包括换行符,很少使用但在文件名中有效)的文件。

destdir=~/testfolder/
while read -u 5 -r -d '' file
do
  name=$(basename "$file")
  ffmpeg -i "$file" -q 1 "$destdir/${file}_%d.jpeg" </dev/null
done 5< <(find . -name "*.mp4" -print0)

basename命令是一个外部程序。您可以使用以下行仅使用 shell 扩展来获得相同的结果:

name=${file%/}
name=${name##*/}

你既不需要基名也不需要循环; 您可以使用 -type f 来避免 find 在其结果中报告目录,并结合 -exec 选项直接执行您的命令。

像这样的东西应该适用于你所有的 mp4 文件:

find . -type f -name '*.mp4' -exec bash -c 'ffmpeg -i [=10=] -q 1 [=10=]'_'%d.jpeg' {} \; 

查看小演示测试:

$ find . -type f -name 'a*.txt' -exec bash -c 'echo ffmpeg -i [=11=] ' {} \; 
ffmpeg -i ./a.txt
ffmpeg -i ./a spaced file.txt
ffmpeg -i ./aa.txt
ffmpeg -i ./cheatsheets/awk-cheat-sheet-gv.txt

如您所见,第二个文件的文件名中有空格,但被 find 正确处理。
相反,这样的间隔文件将以 for loop 中断。

如果您坚持用循环来完成这项工作,那么这必须是 Fred 所建议的 while 循环。

作为对 Fred 解决方案的修改,您可以使用 find-printf 功能避免使用 basename:

while read -r -d '' file;do 
  ffmpeg -i "$file" -q 1 "${file}_%d.jpeg"
done < <(find . -name "*.mp4" -printf %f\0)

-printf %f 根据 find 的手册页打印剥离的文件名,并在每个文件名后附加 \0(空字符)我们确保正确的文件名处理,即使名称包含空格或其他特殊字符。

小测试:

$ while read -r -d '' file;do echo "ffmpeg -i $file -q 1 ${file}_%d.jpeg";done < <(find . -name "a*.txt" -printf %f\0)
ffmpeg -i a.txt -q 1 a.txt_%d.jpeg
ffmpeg -i a spaced file.txt -q 1 a spaced file.txt_%d.jpeg
ffmpeg -i aa.txt -q 1 aa.txt_%d.jpeg
ffmpeg -i awk-cheat-sheet-gv.txt -q 1 awk-cheat-sheet-gv.txt_%d.jpeg