【问题标题】:batch rename file extensions in subdirectories批量重命名子目录中的文件扩展名
【发布时间】:2013-07-01 12:23:01
【问题描述】:

我正在尝试在 linux 中创建一个批处理文件,它允许我更改多个子目录中文件的扩展名。经过大量搜索和试验,我发现似乎是一个解决方案:

find /volume1/uploads -name "*.mkv" -exec rename .mkv .avi {} +

运行脚本时出现以下错误:

find: -exec CMD must end by ';'

我已经尝试添加 ;和 \; (带或不带+)但无济于事。该命令有什么问题,我该如何解决?

编辑:在带有 DSM 4.2 的 Synology NAS 上运行

【问题讨论】:

    标签: shell unix automation busybox


    【解决方案1】:

    您必须转义所有将被bash 解释的字符。在您的情况下,这些是分号和 花括号(您忘记在代码中转义后者):

    find /volume1/uploads -name "*.mkv" -exec rename .mkv .avi \{\} \;
    

    {}(在我们的例子中为\{\})扩展为文件名,所以实际调用看起来像rename .mkv .avi /volume1/uploads/foo/bla.mkv(这不是/usr/bin/rename需要的确切语法,至少在我的系统上) . 相反,它会是这样的:

    find /volume1/uploads -name "*.mkv" -exec rename 's/\.mkv$/.avi/' \{\} \;
    

    更新

    如果您不想(或不能)使用 perl 的 rename 脚本,您可以使用以下简单的 bash 脚本并将其保存为 /tmp/rename.sh

    #!/bin/sh
    INFILE=$1
    OUTFILE="${INFILE%.mkv}.avi"
    echo "moving ${INFILE} to ${OUTFILE}"
    mv "${INFILE}" "${OUTFILE}"
    

    使其可执行 (chmod u+x /tmp/rename.sh) 并调用:

    find /volume1/uploads -name "*.mkv" -exec /tmp/rename.sh \{\} \;
    

    更新2

    原来这个问题真的不是bash的问题,而是busybox的问题。

    使用像busybox这样有限的shell解释器,最简单的解决方案就是追加新的文件扩展名:

    find /volume1/uploads -name "*.mkv" -exec mv \{\} \{\}.avi \;
    

    【讨论】:

    • 运行 find /volume1/uploads -name "*.mkv" 给了我所有我感兴趣的文件,但是当转义大括号和分号时,我收到以下错误(对于找到的每个文件): find: rename: No such file or directory
    • 嗯,是你的示例代码使用了rename,我假设你知道如何使用它(而且它确实在那里)。 -exec 标志只会获取一个二进制文件并运行它,因此您显然必须确保您的系统上有一个 rename 二进制文件。这里(在 debian/sid 盒子上)它带有perl。无论如何,我会更新答案以使用适合您需求的小示例脚本
    • 正如您可能已经猜到的那样,当它涉及到 shell 脚本时,我是一个完整的 n00b。感谢您的帮助!我已关注您的更新(创建第二个文件,chmod 并从第一个文件运行),但我收到另一个错误:每个找到的文件“没有这样的文件或目录”。
    • 您是否将重命名脚本的完整路径 提供给find?如果没有,你可能应该;如果你这样做了,我已经稍微更新了脚本,所以它会打印一些内容来告诉你它要做什么。也许您可以从打印输出中猜出哪里出了问题。
    • 一直提示找不到文件错误,所以我尝试在-exec之后的命令中直接运行重命名功能(文件2)。这给出了一个新错误:“不是目录”(它在文件名后面附加 / )
    【解决方案2】:

    不确定您的 DSM 4.2 操作系统上的 findrename 命令有何不同,因此请尝试以下操作:

    find /volume1/uploads -name "*.mkv" | while read filename; 
    do mv -v "${filename}" "$(echo "${filename}" | sed -e 's/\.mkv$/\.avi/')"
    done
    

    【讨论】:

      猜你喜欢
      • 2010-11-04
      • 1970-01-01
      • 2015-12-12
      • 2010-09-18
      • 2013-07-13
      • 2022-01-15
      • 2019-07-05
      • 1970-01-01
      • 2015-01-23
      相关资源
      最近更新 更多