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