Recursively rename files using find and sed

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/` ;

NB: there's an extra echo after exec so that the command is printed instead of run while I'm testing it.

When I run it the output for each matched filename is:

mv original original

ie the substitution by sed has been lost. What's the trick?


This happens because sed receives the string {} as input, as can be verified with:

find . -exec echo `echo "{}" | sed 's/./foo/g'` ;

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.

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/'

(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.)


To solve it in a way most close to the original problem would be probably using xargs "args per command line" option:

find . -name *_test.rb | sed -e "p;s/test/spec/" | xargs -n2 mv

It finds the files in the current working directory recursively, echoes the original file name ( p ) and then a modified name ( s/test/spec/ ) and feeds it all to mv in pairs ( xargs -n2 ). Beware that in this case the path itself shouldn't contain a string test .


你可能想要考虑其他方式

for file in $(find . -name "*_test.rb")
do 
  echo mv $file `echo $file | sed s/_test.rb$/_spec.rb/`
done
链接地址: http://www.djcxy.com/p/78330.html

上一篇: 找到:缺少参数

下一篇: 使用find和sed递归重命名文件