Search code examples
linuxbashrenamefishbatch-rename

How to rename a consistently-named subdirectory across multiple directories?


I'm wanting to rename

123/1/ -> 123/v1/
foo/1/ -> foo/v1/
bar/1/ -> bar/v1/
345/1/ -> 345/v1/

I've searched and found a few related solutions, but not quite sure what is best in this instance. e.g.,

find . -wholename "*/1" -exec echo '{}' \;

successfully prints out all the paths relative to ., but {} expands to ./foo/1/, so I can't move from {} to {}/v1 for instance. I also tried

find . -wholename "*/1" -exec mv '{}' $(echo '{}' | sed 's/1/v1/') \;

with the idea that I would be invoking mv ./foo/1 ./foo/v1, but apparently it tries to move .foo/1/ to a subdirectory of itself.

Anyhow, just looking for the simplest way to do this bulk renaming. To be clear, I'm trying to move the literal subdirectory 1 to v1, not also 2 to v2.


Solution

  • Like this, using perl rename (which may be different than the rename already existing on your system, use rename --version to check):

    rename -n 's|([^/]+/)(1)|$1v$2|' */1/ 
    

    remove -n (dry-run) when the outputs is ok for you.

    (note that you can use globstar on bash or something similar on other shells to recurse into deeper sub-directories)