使用 find 和 sed 递归地重命名文件 [英] Recursively rename files using find and sed
问题描述
我想浏览一堆目录并将所有以 _test.rb 结尾的文件重命名为以 _spec.rb 结尾.这是我从来没有完全弄清楚如何用 bash 做的事情,所以这次我想我会付出一些努力来搞定它.到目前为止,我还不够,我最大的努力是:
I want to go through a bunch of directories and rename all files that end in _test.rb to end in _spec.rb instead. It's something I've never quite figured out how to do with bash so this time I thought I'd put some effort in to get it nailed. I've so far come up short though, my best effort is:
find spec -name "*_test.rb" -exec echo mv {} `echo {} | sed s/test/spec/` ;
注意:在 exec 之后有一个额外的回显,以便在我测试它时打印而不是运行命令.
当我运行它时,每个匹配的文件名的输出是:
When I run it the output for each matched filename is:
mv original original
即sed 的替换已丢失.有什么诀窍?
i.e. the substitution by sed has been lost. What's the trick?
推荐答案
发生这种情况是因为 sed
接收字符串 {}
作为输入,可以通过以下方式验证:
This happens because sed
receives the string {}
as input, as can be verified with:
find . -exec echo `echo "{}" | sed 's/./foo/g'` ;
为目录中的每个文件递归打印 foofoo
.这种行为的原因是管道在 shell 展开整个命令时执行一次.
which prints foofoo
for each file in the directory, recursively. The reason for this behavior is that the pipeline is executed once, by the shell, when it expands the entire command.
没有办法以 find
对每个文件执行它的方式引用 sed
管道,因为 find
没有t 通过 shell 执行命令并且没有管道或反引号的概念.GNU findutils 手册解释了如何通过将管道放在单独的 shell 脚本中来执行类似的任务:
There is no way of quoting the sed
pipeline in such a way that find
will execute it for every file, since find
doesn't execute commands via the shell and has no notion of pipelines or backquotes. The GNU findutils manual explains how to perform a similar task by putting the pipeline in a separate shell script:
#!/bin/sh
echo "$1" | sed 's/_test.rb$/_spec.rb/'
(可能有一些不正当的方式使用 sh -c
和大量引号在一个命令中完成所有这些操作,但我不会尝试.)
(There may be some perverse way of using sh -c
and a ton of quotes to do all this in one command, but I'm not going to try.)
这篇关于使用 find 和 sed 递归地重命名文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!