How to iterate a zero padded integer in bash?

In bash, numbers with leading zeros are considered as octal. To force bash to consider them as decimal, you can add a 10# prefix:

next_number=$(printf %06d "$((10#$current_number + 1))")

Or with bash 3.1 or above, to avoid the forking:

printf -v next_number %06d "$((10#$current_number + 1))"

(note that it doesn't work for negative numbers as 10#-010 is seen as 10#0 - 010 in bash, so both $((10#-10)) and $((-10#-10)) expand to -8).

See also:

$ printf 'A%06d\n' {5..12}
A000005
A000006
A000007
A000008
A000009
A000010
A000011
A000012

Or:

$ printf '%s\n' {A..C}{00008..00012}
A00008
A00009
A00010
A00011
A00012
B00008
B00009
B00010
B00011
B00012
C00008
C00009
C00010
C00011
C00012

Or:

$ seq -f A%06g 5 12
A000005
A000006
A000007
A000008
A000009
A000010
A000011
A000012

Perl to the rescue:

perl -E '$x = "A001"; say $x++ for 1 .. 1002' 

Output:

A001
A002
A003
A004
A005
A006
A007
A008
A009
A010
A011
...
A996
A997
A998
A999
B000
B001
B002

The ++ operator handles both letters and numbers.


For historical reasons, numerical operations in Bourne/POSIX-style shells parse integer constants with a leading 0 digit as octal rather than decimal. So 08 in an arithmetic operating is a syntax error, the successor of 07 is 8, and 010 is equivalent to 8.

You can use normal arithmetic and then pad the numbers when printing them with the printf builtin.

next_number=$(($current_number + 1))
printf -v padded_next_number %06d "$next_number"

The -v option to printf is bash-specific; the POSIX way is

next_number=$(($current_number + 1))
padded_next_number=$(printf %06d "$next_number")

Here's another approach which was useful in historical systems that didn't have a printf command, and can still be useful for performance in the few shells that don't have printf as a builtin. Instead of counting from 1, count from 1000001. That way, your numbers never have to have leading zeroes. When you use the number, strip off the leading 1 digit.

number=1000000
while … ; do
  number=$((number+1))
  echo "${number#1}"
  …
done