在子目录中批量重命名文件扩展名

3

我正在尝试在Linux中创建一个批处理文件,以便我可以更改多个子目录中文件的扩展名。经过大量搜索和实验,我找到了似乎是解决方案的方法:

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

当运行脚本时,我遇到了以下错误:
find: -exec CMD must end by ';'

我曾尝试添加 ; 和 \; (带或不带 +),但均无效。这个命令有什么问题,并且我该如何修复它?
编辑:在运行 DSM 4.2 的 Synology NAS 上运行。
2个回答

0

你必须转义所有会被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。 - Roland
正如你可能猜到的,对于shell脚本我是个彻头彻尾的新手。非常感谢你的帮助!我按照你的更新(创建第二个文件,使用chmod命令并从第一个文件运行)进行了操作,但是我遇到了另一个错误:"找不到该文件或目录",对于每个找到的文件都是如此。 - Roland
它一直报文件未找到的错误,所以我尝试在-exec后直接运行重命名函数(文件2)的命令。这会产生一个新的错误:“不是目录”(它将文件名附加了一个/)。 - Roland
“/tmp/rename.sh /flub.mkv” 会打印什么? - umläute
运行命令“sh tmp/rename.sh /flub.mkv”会出现以下结果: .avi/flub.mkvmkv ':没有这个文件或目录 - Roland
显示剩余3条评论

0

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接