递归迭代文件时处理带有空格的名称

递归迭代文件时处理带有空格的名称

.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 循环不会执行此操作(除非启用dotglobshell 选项)。

其他相关问题:

相关内容