How to do bulk file rename
more from dev
Mar 18, 09

How can you do bulk file rename using shell tools?

The wrong answer is: mv *.OLD *.NEW

The easy answer is a shell loop, should be pretty straightforward. Or maybe even a simple Perl/Ruby/etc. script.

But it's also do-able using find with some other tools. Turns out that's rather awful. This is what I came up with to make it actually work using find, and as far as I can tell, it adds zero practical value over a basic shell loop. I spent a few minutes trying to use -exec, but that got hairy when using {} twice, and also when the output contained full paths from subdirectory traversals.

find . -name "*.OLD" | sed 's/^\(.*\).\(OLD\)/cp \1.\2 \1.NEW/' | awk '{system $0}'

Another option would be using xargs. If you wanted to rename all ".txt" as ".txt.OLD" (variation from above), that would be:

find . -name "*.txt" | xargs -I % cp % %.OLD

The example I initially gave is a little harder -- .OLD to .NEW -- you could use sed, too, in order to remove the file extension, like this:

find . -name "*.OLD" | sed 's/^\(.*\).OLD/\1/' | xargs -I % cp %.OLD %.NEW

Or you could use basename instead of sed, and call xargs twice, like this:

find . -name "*.OLD" | xargs basename -s .OLD | xargs -I % cp %.OLD %.NEW

This is a nice interview question for someone with Unix chops, because it can (should?) lead to a short discussion of shell tools.