.mkv
我正在尝试将带有子文件夹的文件夹结构中的所有文件递归转换为.mp4
.
我得到了一条仅适用于当前文件夹的标准行
for video in *.mkv; do ffmpeg -i "$video" -acodec aac -ac 2 "${video%.*}".mp4; rm "$video"; done
所以我想我会做一些类似的东西
for video in $(find . -name *.mp4); do ffmpeg -i "$video" -acodec aac -ac 2 "${video%.*}".mkv; rm "$video"; done
但这似乎在包含空格的文件夹上失败。谁能指出我的错误?
答案1
您的错误在于find
在命令替换中使用。命令替换始终会生成单个字符串。如果您将替换不加引号,则该字符串将在空格、制表符和换行符上进行分割(默认情况下)。分割后的单词将被处理以进行文件名通配。生成的字符串是循环将迭代的内容,这不是您想要的。
适用于当前目录的循环(解决文件名以破折号开头的问题):
for video in ./*.mkv; do
ffmpeg -i "$video" -acodec aac -ac 2 "${video%.*}".mp4
rm "$video"
done
通过启用**
通配模式(并使用nullglob
以避免在没有匹配项时完全运行循环),更改为递归工作:
shopt -s globstar nullglob
for video in ./**/*.mkv; do
ffmpeg -i "$video" -acodec aac -ac 2 "${video%.*}".mp4
rm "$video"
done
上面的两个循环不会关心文件类型,并且会愉快地提供ffmpeg
符号链接、目录或任何其他非常规类型的文件,只要名称与给定模式匹配即可。
或者,将路径名的递归生成委托给find
(也仅选择常规文件):
find . -name '*.mkv' -type f -exec sh -c '
for video do
ffmpeg -i "$video" -acodec aac -ac 2 "${video%.*}".mp4
rm "$video"
done' sh {} +
上面的代码还会找到与模式匹配的隐藏名称,而前两个 shell 循环不会执行此操作(除非启用dotglob
shell 选项)。
其他相关问题: