71

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)
2

6 Answers 6

105

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
5
  • 10
    After just found out about the echo {08..10} solution, however, it is only introduced for bash version 4 and up.
    – Bernhard
    Jan 4, 2013 at 9:05
  • That makes me a little uncomfortable that bash does that. For a bunch of utilities (for example perl) a leading zero indicates an octal number. I suppose it is not often you want a sequence of octal numbers...
    – kurtm
    Oct 11, 2013 at 15:01
  • 5
    It should be noted that you can also prefix the numbers when giving then to seq with the -w switch like so: seq -w 003 produces the numbers 001, 002, and 003.
    – slm
    May 6, 2014 at 19:08
  • @kurtm don't worry about leading zeroes. That could hurt when something tries to parse a number. What this is really useful at is to generate a file name sequence foo_00001.someextension where nearly all sorting contexts provide a sane ordering. Jan 16, 2017 at 15:11
  • The echo {08..10} option is not working on centos bash
    – AveryLiu
    Oct 19, 2020 at 4:23
13

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).

1
  • I did not think about this solution (although in my case I actually also want to number 0001 1000, but your principle works of course.
    – Bernhard
    May 22, 2014 at 14:01
10

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 ".

2
  • Thanks for your answer. I am aware of the printf solution, but it is not really making this easier. I am hoping that there is some hidden trick that does the job :)
    – Bernhard
    Jan 4, 2013 at 8:49
  • This is the only answer that seems versatile enough to handle any circumstance for origin of the number to pad. I'm using a counter as I loop through files. This printf solution zero pads flawlessly while all others seem to focus on generating zero-padded numbers rather than zero-padding existing numbers.
    – mightypile
    Jan 2, 2015 at 2:11
9

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
1
  • I accepted this answer above the other answers, because it satisfies the request for Bash 3.x. Especially as I needed the for loop anyhow.
    – Bernhard
    Jan 25, 2013 at 23:06
2

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
-3
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 ;)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .