Rename files by incrementing a number within the filename

I think that it should do the work:

#!/bin/bash

NEWFILE=$1

for file in `ls|sort -g -r`
do
    filename=$(basename "$file")
    extension=${filename##*.}
    filename=${filename%.*}

    if [ $filename -ge $NEWFILE ]
    then
        mv "$file" "$(($filename + 1))".$extension
    fi
done

Script takes one parameter - number of you new image.

PS. Put script in another directory than your images. In images directory there should be only images named in this way that you described.


This would be easier in zsh, where you can use

  • the On glob qualifier to sort matches in decreasing order (and n to use numerical order, in case the file names don't all have leading zeroes to the same width);
  • the (l:WIDTH::FILLER:) parameter expansion flag to pad all numbers to the same width (the width of the larger number).
break=$1   # the position at which you want to insert a file
setopt extended_glob
width=
for x in [0-9]*(nOn); do
  n=${x%%[^0-9]*}
  if ((n < break)); then break; fi
  ((++n))
  [[ -n $width ]] || width=${#n}
  mv $x ${(l:$width::0:)n}${x##${x%%[^0-9]*}}
done

In bash, here's a script that assumes files are padded to a fixed width (otherwise, the script won't rename the right files) and pads to a fixed width (which must be specified).

break=$1      # the position at which you want to insert a file
width=9999    # the number of digits to pad numbers to
files=([0-9]*)
for ((i=#((${#files}-1)); i>=0; --i)); do
  n=${x%%[^0-9]*}
  x=${files[$i]}
  if ((n < break)); then continue; fi
  n=$((n + 1 + width + 1)); n=${n#1}
  mv -- "${files[$i]}" "$n${x##${x%%[^0-9]*}}"
done

There doesn't seem to be much recent interest in this question but, should someone stumble upon it, there are three issues here.

  • One is how to select files to rename based on semantic criteria (range is not lexical and cannot be specified by wildcards or even regular expressions-- automata theory says that this is more complex than an NFA).

  • The second is how to change a name by modifying a portion of it.

  • The third is how to avoid name collision.

A script in Bash and many other languages can do this specific transform, but most of us would rather not have to write a program every time we want to rename a bunch of files.

With my (free and open source) rene.py you can do what you want but it takes two invocations to avoid the name collision problem.

  1. First
    rene ?.*/#7-80  %?.* B
    
    increments all names in the range, adding a prefix of % to avoid existing names.
  2. Then
    rene %* *
    
    removes this prefix from those files that have it.

I describe this at https://sourceforge.net/p/rene-file-renamer/discussion/examples/thread/f0fe8aa63c/

Tags:

Bash

Rename