如何使用Bash脚本重命名当前目录及其子目录中的文件?

6
我可以使用“重命名”命令将缺失的字符添加到当前目录中所有文件名,操作步骤如下:
echo "Renaming files..."
rename -v "s/^abcd124(.+)/abcd1234$1/" *.wav.gz;
echo "Done."

然而,我希望对当前目录以及其所有子目录进行此操作。我尝试了以下方法:

echo "Renaming files..."
for dir in $(find ./ -type d); do
    rename -v "s/^$dir\/abcd124(.+)/$dir\/abcd1234$1/" *.wav.gz;
done;
echo "Done."

然而,如果$dir变量包含这些特殊字符之一:{}[]()^$.|*+?\,那么它们没有被正确地用\转义,我的脚本会失败。

解决这个问题的最佳方法是什么?此外,您认为使用awk解决这个问题怎么样(优缺点)?

4个回答

6

你也可以尝试以下方法:

find . -name "*.wav.gz" | xargs rename -v "s/abcd124*/abcd1234$1/"

它适用于具有可用“xargs”命令的较新的Unix系统。请注意,我稍微编辑了正则表达式。


文件名包含空格会失败。 - user unknown
这是正确的。虽然我现在需要重命名的文件名中没有空格,但我未来要处理的文件可能会有。我该如何让脚本考虑到文件名中的空格? - bumbleshoot

3

尝试:

find ./ -type d -execdir rename -v "s/^abcd124(.+)/abcd1234\1/" *.wav.gz ";"

找到已经提供了一个文件的迭代器 - 你不需要在它周围加上for或者后面跟着xargs,这些通常是看到的。好吧 - 在很少的情况下,它们可能会有所帮助,但通常不需要。
在这里,-execdir很有用。Gnu-find有它;我不知道你的find是否也有它。
但你需要确保在你启动这个命令的目录中没有*.wav.gz文件,否则你的shell将扩展它,并将扩展后的名称交给rename。
注意:我从rename那里得到了一个警告,说我应该在正则表达式中用$1替换\1,但如果我这样做,模式就无法被捕获。我必须使用\1才能使它工作。
这里有另一种方法。为什么要搜索目录,如果我们搜索wav.gz文件呢?
find . -name "*.wav.gz" -exec rename -v "s/^abcd124(.+)/abcd1234\1/" {} ";"

没成功!:( 我运行了它,但是没有重命名任何东西。我尝试删除“*.wav.gz”周围的引号,在这种情况下,它将一个文件重命名为abcd1234(无法识别$1),然后无法重命名其他文件,因为它们与abcd1234冲突。谢谢你的建议,我学到了很多。还有其他想法吗? - bumbleshoot
@jessica:你说得对。我修改了代码和解释,请看最后两段。 - user unknown
这也不起作用 - 它会为起始目录中的每个文件都给出警告,不会重命名它们,并且不会查看其子目录。此外,为了我的目的,脚本需要从起始目录内运行,不能为每个文件打印出警告。它需要是无懈可击的! - bumbleshoot
好的,我测试过了,对我有效。现在我进行了第二次尝试(最后两行),我也测试过了。它也有效,但是会给我一个警告,如果我认真对待这个警告,它就不起作用了。当然,你可以通过附加2>/dev/null来抑制警告。或者你打开重命名的perl脚本,在那里抑制/更正它。或者向重命名提出错误报告。或者重写你需要的重命名部分,但我不会这样做。我会接受这些警告。一个程序是否坚不可摧并不取决于警告消息,我可以向你断言,但我也会持怀疑态度。 - user unknown
你给我的最后一个脚本对我也没有起作用——它会警告所有需要重命名的文件(包括文件名中带有空格的文件),但是不会对它们进行重命名! - bumbleshoot
我不明白为什么。我有“find (GNU findutils) 4.4.2”,但是“rename”不支持版本标志。通过“less $(which rename)”可以看到多个不同组织的版本字符串,“# Revision 1.5 1998/12/18 16:16:31 rmb1”是最新的。 - user unknown

1

1
在bash 4中:
shopt -s globstar
rename -v "s/^$dir\/abcd124(.+)/$dir\/abcd1234$1/" **/*.wav.gz;

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