How to create a sequence with leading zeroes using brace expansion

When I use the following, I get a result as expected:

$ echo {8..10}
8 9 10

How can I use this brace expansion in an easy way, to get the following output?

$ echo {8..10}
08 09 10

I now that this may be obtained using seq (didn’t try), but that is not what I am looking for.

Useful info may be that I am restricted to this bash version. (If you have a zsh solution, but no bash solution, please share as well)

$ bash -version
GNU bash, version 3.2.51(1)-release (x86_64-suse-linux-gnu)

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Prefix the first number with a 0 to force each term to have the same width.

$ echo {08..10}
08 09 10

From the bash man page section on Brace Expansion:

Supplied integers may be prefixed with 0 to force each term to have
the same width. When either x or y begins with a zero, the shell
attempts to force all generated terms to contain the same number of
digits, zero-padding where necessary.

Also note that you can use seq with the -w option to equalize width by padding with leading zeroes:

$ seq -w 8 10
08
09
10

$ seq -s " " -w 8 10
08 09 10

If you want more control, you can even specify a printf style format:

$ seq -s " " -f %02g 8 10
08 09 10

Method 2

if you use printf

printf "%.2d " {8..10}

this will force to be 2 chars and will add a leading 0. In case you need 3 digits you can change to “%.3d “.

Method 3

I have the same bash version of the original poster (GNU bash, version 3.2.51(1)-release) and {08..12} doesn’t work for me, but the following does:

for i in 0{8..9} {10..12}; do echo $i; done
08
09
10
11
12

It’s a little more tedious, but it does work on the OP version of bash (and later versions, I would assume).

Method 4

Use a range that starts with a constant digit and strip that digit off:

echo  {108..110} | sed 's/ 1//g'

or without using an external command:

a=({108..110}); echo "${a[@]#1}"

For use in a for loop:

for x in {108..110}; do
  x=${x#1}
  …
done

though for this case a while loop would be clearer and works in any POSIX shell:

x=8
while [ $x -le 10 ]; do
  n=$((100+x)); n=${n#1}
  …
  x=$((x+1))
done

Method 5

For reference, I think automatic fixed-width only occurs with the latest version of bash:

$ bash -version
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.

$ echo test{00..05}
test0 test1 test2 test3 test4 test5

Method 6

for i in $(seq -s " " -f %0${zeros}g $ini $fin); do ....;done

zeros, ini and fin are variables, so its easy to fit to your needs. It pads the digits to $zeros zeros from $ini to $fin without problems 😉


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x