我想通过一系列目录并重命名所有以_test.rb结尾的文件,以_spec.rb结尾。这是一个我从来没有搞清楚如何做的bash所以这一次,我认为我会付出一些努力,使它钉牢。我到目前为止虽然很短,但我最大的努力是:
find spec -name "*_test.rb" -exec echo mv {} `echo {} | sed s/test/spec/` \;@H_502_3@注意:在exec之后有一个额外的回声,所以命令打印,而不是运行,而我测试它。 @H_502_3@当我运行它的输出每个匹配的文件名是:
mv original original@H_502_3@即sed的取代已经丢失。什么诀窍?
发生这种情况是因为sed接收到字符串{}作为输入,可以通过验证:
find . -exec echo `echo "{}" | sed 's/./foo/g'` \;@H_502_3@它以递归方式打印目录中的每个文件的foofoo。这种行为的原因是,当扩展整个命令时,管道由shell执行一次。 @H_502_3@没有办法引用sed管道,因为find将为每个文件执行它,因为find不通过shell执行命令,并且没有管道或反引号的概念。 GNU findutils手册解释了如何通过将管道放在单独的shell脚本中来执行类似的任务:
#!/bin/sh echo "$1" | sed 's/_test.rb$/_spec.rb/'@H_502_3@(可能有一些不正当的方式使用sh -c和一吨引号在一个命令中做所有这一切,但我不会尝试。)