使用 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.
没有办法引用 sed
管道,这样 find
会为每个文件执行它,因为 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屋!