Bash – Rename Multiple Directories Decrementing Sequence Number

bashrename

I have a directory which contains a number of subdirectories with names on the format dir.##. The prefix is always the same, and the suffix is 1-3 digits in a strictly incrementing sequence. Thus, something similar to:

dir.0
dir.1
dir.2
dir.3
...
dir.9
dir.10
dir.11
...
dir.298
dir.299
dir.300

First, I want to delete the first few such directories. This is trivial.

Then, I want to rename all subsequent directories to shift the numerical suffixes such that e.g. dir.7 becomes dir.0, dir.8 becomes dir.1, dir.10 becomes dir.3, etc. That is, shift each suffix (treated as a number) by a given, constant offset.

How do I perform such a rename operation without renaming each directory separately and manually?

I'm okay with using a separate tool for it, but it would be nice if I can do it all in bash without "exotic" software.

Best Answer

This decrementing can be done in a pretty low-tech way: generate the list, start at the beginning. It's not that easy to “productize” by handling all cases, but it's little more than a one-liner if you're willing to hard-code things like the maximum number of digits and to assume that there are no other files called dir.*. Using bash syntax, tuned towards less typing:

i=0
for x in dir.{?,??,???}; do
  mv "$x" "${x%.*}.$i"
  ((++i))
done

Note that it has to be dir.{?,??,???} and not dir.* to get dir.9 before dir.10.

In zsh you could make this a little more robust at no cost, by using <-> to expand to any sequence of digits and (n) to sort numerically (dir.9 before dir.10).

i=0
for x in dir.<->(n); do
  mv $x ${x%.*}.$i
  ((++i))
done
Related Question