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

时间:2017-02-25 23:06:35

标签: bash file-handling

我正在尝试使用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

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

3 个答案:

答案 0 :(得分:4)

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

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##*/}

答案 1 :(得分:2)

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

这样的东西适用于所有mp4文件:

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

参见一个小型演示测试:

$ find . -type f -name 'a*.txt' -exec bash -c 'echo ffmpeg -i $0 ' {} \; 
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解决方案的修改,您可以使用-printf的{​​{1}}功能避免使用basename:

find

while read -r -d '' file;do ffmpeg -i "$file" -q 1 "${file}_%d.jpeg" done < <(find . -name "*.mp4" -printf %f\\0) 根据-printf %f的手册页打印剥离的文件名,并在每个文件名后附加find(null char)我们确保正确的文件名处理,即使名称包含空格或其他特殊的字符。

小测试:

\\0

答案 2 :(得分:-1)

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