Search code examples
imagebashsortingunixbatch-rename

Rename all files to with four-digit padding, sort by the number values in the filename. bash


In other words, The file with the lowest index should map to 0001.jpg, and the second lowest index should map to 0002.jpg. Something like this:

DSCN-1009.JPG --> 1009.JPG
DSCN-1010.JPG --> 1010.JPG
DSCN-101.JPG --> 0101.JPG
DSCN-102.JPG --> 0102.JPG

or

DSCN-1.JPG --> 0001.JPG
DSCN-2.JPG --> 0002.JPG
DSCN-3.JPG --> 0003.JPG
DSCN-4.JPG --> 0004.JPG

I have this code that renames all files with four-digit padding.

X=1;
for i in *; do                       
  mv "$i" "$(printf %04d.%s "${X%.*}" "${i##*.}")"                      
  let X="$X+1"
done

but sorting of the files is off as it outputs like this (this is not what I want):

DSCN-1009.JPG --> 0009.JPG
DSCN-1010.JPG --> 0010.JPG
DSCN-101.JPG --> 0011.JPG
DSCN-102.JPG --> 0012.JPG

Solution

  • This is based on your script but just changing how the numbers are computed:

    for i in *
    do
        mv "$i" "$(printf %04d.%s "${i//[^0-9]/}" "${i##*.}")"
    done
    

    The key is the bash construct ${i//[^0-9]/}. This removes all non-numbers from the filename. So, if i=DSCN-101.JPG, then ${i//[^0-9]/} becomes just 101. The printf command formats the number zero-padded to four digits.

    ${i//[^0-9]/} is called pattern substitution. In its general form, it looks like ${parameter//pattern/string} where parameter is the variable name. pattern is some regular expression. Everywhere that the regular expression pattern occurs in variable, it is replaced by string. In our case, the regular expression is [^0-9] which matches all non-numbers and string is the empty string. Thus, all non-numbers are replaced with the empty string.