【问题标题】:Run command inside all folders and sub folders with specific extension在具有特定扩展名的所有文件夹和子文件夹中运行命令
【发布时间】:2019-06-29 05:05:17
【问题描述】:

目前,我正在尝试在我的 linux 服务器 (Ubuntu 16.04) 上运行一个命令来重新编码所有 .mp4 文件。但是我在文件夹和子文件夹中有很多文件,我会浪费很多时间手动运行这些命令

这是我的脚本:

for D in ./*; do
    if [ -d "$D" ]; then
        cd "$D"
        for i in *.mp4; do
            ffmpeg -i "$i" -codec copy -acodec copy -shortest -map 0:v -map 0:m:language:eng "${i%.*}.mp4"
        done
        cd ..
    fi
done

但是,我收到了这个错误:

Error: ENOENT: no such file or directory, stat '*.mp4'

我该如何解决这个问题?

谢谢。

【问题讨论】:

    标签: bash shell ffmpeg


    【解决方案1】:

    为此使用find。它为您处理子目录递归。像这样:

    find . -type f -name "*.mp4" -exec ffmpeg -i {} -codec copy -acodec copy -shortest -map 0:v -map 0:m:language:eng {}  \; -print
    
    • find会自动处理当前目录及所有子目录
    • -type f: 只搜索文件
    • `-name "*.mp4": 只有带有 mp4 扩展名的文件
    • -exec COMMAND {} \;:对所有找到的文件执行该命令。 {} 将替换为每个文件的文件名。 \; 结束命令。
    • -print: 将打印处理了哪个文件

    就您的代码而言,目录可能没有任何“*.mp4”文件,因此当您点击此类目录时会出现no such file or directory, stat '*.mp4' 错误。

    【讨论】:

    • 您好,如何使用{} 获取文件名而不使用扩展名?
    • 有时,.mp4 应转换为 .mkv。如果我把{}.mkv 返回{filename}.mp4.mkv
    • 您可以使用 basename 和 dirname 的组合。但您只能使用一次 {}。我会编写一个从 {} 接受文件名的脚本,计算新文件名,然后调用 FFmpeg。然后在 find -exec 中使用该脚本
    • 虽然,如果需要,一个计算新文件名的脚本是个好主意,作为澄清点,POSIX需要find支持,在在某些情况下,在一个命令中多次使用{}。 GNU find 支持在比 POSIX 要求的更广泛的条件下多次使用 {}。作为它当前编写的答案,该代码满足{} 多次使用的POSIX 条件。但是,{}.mkv 这样的形式需要 GNU find 或类似的。
    【解决方案2】:

    示例(没有效果,只做echo ...):

    $ find \
      . \
      -type f \
      -name '*.mp4' \
      -exec sh -c '
        for src in "$@"; do
          dst="${src%.*}.mkv"
          echo ffmpeg ... "$src" ... "$dst"
        done
      ' sh {} + \
      -print \
    ;
    

    您必须将echo ffmpeg ... "$src" ... "$dst" 替换为您的命令行以供生产使用。您可以从示例中删除 -print

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-16
      • 2021-10-08
      • 1970-01-01
      • 2014-08-11
      • 1970-01-01
      • 2016-03-20
      • 2011-03-10
      • 1970-01-01
      相关资源
      最近更新 更多