在文件中查找模式并重命名它们。

62

我使用这个命令来查找符合给定模式的文件,然后将它们重命名为其他名称。

find . -name '*-GHBAG-*' -exec bash -c 'echo mv $0 ${0/GHBAG/stream-agg}' {} \;

当我运行此命令时,我会看到类似于以下的一些输出

mv ./report-GHBAG-1B ./report-stream-agg-1B
mv ./reoprt-GHBAG-0.5B ./report-stream-agg-0.5B

然而最后,当我运行ls命令时,我看到的是旧文件名。


2
对于大多数在谷歌上搜索此问题的人来说,更好的问题是https://dev59.com/rXNA5IYBdhLWcg3wHp-B。 - tripleee
4个回答

96

你正在使用“echo”命令显示你的“mv”命令,而不是实际执行它。更改为:

find . -name '*-GHBAG-*' -exec bash -c 'mv $0 ${0/GHBAG/stream-agg}' {} \;

14
感谢这个解决方案。但是,如果文件名中有空格,请最好用 " 将那些变量包围起来。mv "$0" "${0/GHBAG/stream-agg}" - erickb
1
@erickb 很棒的发现 =) - Kyle
3
我不知道你可以在bash中这样对变量进行替换。太棒了! - Snorfalorpagus
请问为什么只用这个命令:find . -name '-GHBAG-' -exec mv ${0} ${0/GHBAG/stream-agg} {} ; 不能生效,需要使用 bash -c 呢? - Vishal Saxena
@VishalSaxena - 这里是bash在进行字符串替换,而不是find命令 - 如果没有bash,您将无法生成新的文件名。 - Stuart Moore

37

我建议使用rename命令来执行此任务。rename根据指定的Perl正则表达式规则对提供的文件名进行重命名。

在这种情况下,您可以使用:

rename 's/GHBAG/stream-agg/' *-GHBAG-*

谢谢。这个简单多了,但我一直在试验exec - mahmood
当然,使用带有-execfind命令具有递归搜索目录的优点,而rename则没有。但是,rename将更快,因为它不会为每个要重命名的文件生成一个进程。 - anumi
1
@anumi man find 显示 -exec command {} + 作为选项,以仅在所有找到的文件上执行一个实例。尽管如此,我不知道它是否适用于原始问题中的示例。 - F-3000
2
@F-3000:命令应该是 find . -name '*-GHBAG-*' -exec rename 's/GHBAG/stream-agg/' {} +,即使文件名包含空格或换行符,它也能出色地完成工作。 - Jonathan Leffler
不确定是因为我使用了另一个版本的rename,所以我必须使用rename GHBAG stream-agg *-GHBAG-* - Julian
显示剩余3条评论

20

回复anumi的评论,你可以使用“**”来匹配文件夹并递归搜索:

rename 's/GHBAG/stream-agg/' **/*-GHBAG-*

1
我尝试了这个方法,但只对其中一个子目录有效。在运行rename -v 's/:/-/' **/*:*后,find . -name "*:*"仍然会列出一些文件,并且第二次运行重命名时会提示“没有这样的文件或目录”。(Debian 6) - F-3000
1
重命名不是通用的Unix命令。 - Phyo Arkar Lwin

2
这对我的需求很有效,可以替换所有匹配的文件或文件类型。请注意,这是一次非常贪婪的搜索。
# bashrc
function file_replace() {
  for file in $(find . -type f -name "$1*"); do
    mv $file $(echo "$file" | sed "s/$1/$2/");
  done
}

通常我会使用find . -type f -name "MYSTRING*"来先检查匹配项,然后再进行替换。

例如:

file_replace "Slider.js" "RangeSlider.ts"

renamed:    packages/react-ui-core/src/Form/Slider.js -> packages/react-ui-core/src/Form/RangeSlider.ts
renamed:    stories/examples/Slider.js -> stories/examples/RangeSlider.ts

或者放弃文件类型,使其更加贪婪。
file_replace Slider RangeSlider

renamed:    packages/react-ui-core/src/Form/Slider.js -> packages/react-ui-core/src/Form/RangeSlider.js
renamed:    stories/examples/Slider.js -> stories/examples/RangeSlider.js
renamed:    stories/theme/Slider.css -> stories/theme/RangeSlider.css

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