【问题标题】:Loop recursively for specific extension and subfolders递归循环特定扩展名和子文件夹
【发布时间】:2017-02-10 14:21:43
【问题描述】:

我一直在尝试将 flac 转换为 m4a,我有以下脚本可以完成这项工作,但它不是递归的:

for f in *.flac; do
    ffmpeg -i "$f"  -vf "crop=((in_w/2)*2):((in_h/2)*2)" -c:a alac "${f%.flac}.m4a"
done

对于递归,我确实尝试了几种方法,但都没有奏效,这是我尝试过的 (文件名上的空格是这里的问题)

for f in `find . $PWD -iname *.flac`; do
    ffmpeg -i "$f"  -vf "crop=((in_w/2)*2):((in_h/2)*2)" -c:a alac "${f%.flac}.m4a"
done

还有这个

find . -type f -iname "*.flac" -print0 |
    while IFS= read -r -d $'\0' line; do
        echo "$line"
        ffmpeg -i "$line"  -vf "crop=((in_w/2)*2):((in_h/2)*2)" -c:a alac "${f%.flac}.m4a"; done   
    done

它们都不起作用。

【问题讨论】:

    标签: bash recursion ffmpeg


    【解决方案1】:

    由于分词,第二次尝试失败:find 的输出被拆分。

    您的最后一次尝试会成功,但是done 太多了,您在"${f%.flac}.m4a" 中使用$f,它应该是${line%.flac}.m4a"

    我会改用 glob(需要 shopt -s globstar):

    for fname in **/*.flac; do
        ffmpeg -i "$fname"  -vf "crop=((in_w/2)*2):((in_h/2)*2)" \
            -c:a alac "${fname%.flac}.m4a"
    done
    

    这会搜索当前目录的整个子树而不需要find


    1 Bash 4.0 或更新版本

    【讨论】:

    • 工作得很好,我的任何方法都不起作用(在纠正了您在此处指出的错误之后),它只是在第一次编码后挂起(输入命令:|all
    【解决方案2】:

    -execdir 选项与find 一起使用:

    find . -name "*.flac" -execdir bash -c 'ffmpeg -i "$0"  -vf \
    "crop=((in_w/2)*2):((in_h/2)*2)" -c:a alac "${0%.flac}.m4a"' {} \;
    

    递归地将.flac 文件匹配/重新编码为.m4a 并将它们保存在同一目录中。使用 -exec 而不是 -execdir 任何重新编码的文件都将保存到执行上述命令的位置 — 这可能不是您想要的。

    -execdir 主节点与 -exec 主节点相同 该实用程序将从目录中执行的异常 保存当前文件。

    此解决方案效果很好,特别是如果您的 bash 版本不包含 shoptglobstar

    Another example of ffmpeg re-encoding using find and -execdir。 (更复杂)

    【讨论】:

      猜你喜欢
      • 2012-11-29
      • 2011-08-21
      • 2020-06-02
      • 1970-01-01
      • 1970-01-01
      • 2021-10-08
      • 2023-03-28
      • 1970-01-01
      相关资源
      最近更新 更多