Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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?

share|improve this question
I can tell you what's wrong, but I'm not sure how to tell you to fix it: bash is immediately executing echo {} | sed s/test/spec/, which produces {}, then bash executes the find command. Have you checked to see whether your distribution has a good rename program? – DerfK Jan 25 '11 at 13:37
Please don't cross-post. – Dennis Williamson Jan 25 '11 at 20:36
up vote 3 down vote accepted

If you don't have rename (it's a really short Perl script) or your rename is the more simplistic util-linux version or you simply want to know how to make your command work: you just need to send it to the shell for execution:

find spec -name "*_test.rb" -exec sh -c 'echo mv "$1" "$(echo "$1" | sed s/test.rb\$/spec.rb/)"' _ {} \;
share|improve this answer

Too complicated. If you have the rename command available, you could try the following:

find . -name "*_test.rb" -print0 | xargs -0 rename "s/_test/_spec/" 

This finds the relevant files, sends them to xargs which in turn uses the rename tool (which renames files according to the given perl regex).

share|improve this answer
+1 for -print0. Also, I'd make the regexp pattern as axplicit as possible: "s/_test.rb$/_spec.rb/" just to be on the safe side. – SmallClanger Jan 25 '11 at 15:34
note that only works if you happen to have the perl script version of rename, not the standard rename that comes with util-linux. – Phil Hollenback Jan 25 '11 at 21:35

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.