Recursively rename files using find and sed

opsb picture opsb · Jan 25, 2011 · Viewed 85.4k times · Source

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

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

Answer

ramtam picture ramtam · Jul 29, 2012

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.