Batch rename files to a sequential numbering

I can't think of a solution that handles incrementing the counter in a more clever way, but this should work:

i=0
for fi in abc_??????.png; do
    mv "$fi" abc_$i.png
    i=$((i+1))
done

It should be safe to use abc_*.png because it is expanded before the first mv is ever executed, but it can be useful to be very specific in that you only want files with a six-character timestamp at the end.


With rename utility as part of Perl packages, you would do:

rename -n 'our $i; s/_.*/sprintf("_%03d.png", $i++)/e' *.png

Note: -n is for dry run, remove it to rename apply on files.


With zsh:

typeset -A count
incr='++count[$1/$2]'
(zmv -n '([^0-9]##)<->(*)(#qn)' '$1${(l:3::0:)$((incr))}$2')

Remove the -n when happy.

(note the extra step using the incr variable to avoid the ACE vulnerability)

Example:

$ ls
a1b.png  abc_128390.png  abc_159084.png  x12y.png
a2b.png  abc_138493.png  a.png           x2y.png
$ typeset -A count
$ incr='++count[$1/$2]'
$ (zmv -n '([^0-9]##)<->(*)(#qn)' '$1${(l:3::0:)$((incr))}$2')
mv -- a1b.png a001b.png
mv -- a2b.png a002b.png
mv -- abc_128390.png abc_001.png
mv -- abc_138493.png abc_002.png
mv -- abc_159084.png abc_003.png
mv -- x2y.png x001y.png
mv -- x12y.png x002y.png