Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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.

share|improve this question

3 Answers 3

up vote 6 down vote accepted

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
share|improve this answer
    
The bash example (with Glenn's edit for the substitution expression) did exactly what I wanted. Thank you both! –  Michael Kjörling Dec 3 '12 at 22:08

You can also use graphical tool KRename.

Here are the steps:

  1. choose files
  2. choose option to rename files
  3. turn on JavaScript plugin\
  4. set field Prefix to empty, Suffix: empty, Filename: use original name, Extension: other extension: [js;krename_extension-OFFSET] where OFFSET is value that you need to decrement.
share|improve this answer

Another approach:

n=7   # number to delete
max=$(printf "%s\n" dir.* | grep -o '[[:digit:]]*' | sort -n | tail -1)
for (( i=0; i<n; i++)); do rm -r "dir.$i"; done
for (( i=n; i<=max; i++ )); do mv "dir.$i" "dir.$((i-n))"; done
share|improve this answer
    
The quotes in the rm and mv command arguments are not strictly necessary since we know the contents of the generated directory name will not contain whitespace. –  glenn jackman Dec 4 '12 at 0:02
1  
while technically true, quoting is generally considered best practice. –  laebshade Dec 4 '12 at 3:44

Your Answer

 
discard

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.