68

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)
Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
Bernhard
  • 11,992
  • 4
  • 59
  • 69

6 Answers6

102

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
dogbane
  • 29,087
  • 16
  • 80
  • 60
  • 10
    After just found out about the `echo {08..10}` solution, however, it is only introduced for bash version 4 and up. – Bernhard Jan 04 '13 at 09: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 '13 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 06 '14 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. – Stéphane Gourichon Jan 16 '17 at 15:11
  • The echo {08..10} option is not working on centos bash – AveryLiu Oct 19 '20 at 04: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).

drs
  • 5,363
  • 9
  • 40
  • 69
Gregory Dulin
  • 131
  • 1
  • 2
  • 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 '14 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 ".

BitsOfNix
  • 5,057
  • 2
  • 25
  • 34
  • 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 04 '13 at 08: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 02 '15 at 02:11
8

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
Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
  • 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 '13 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
manatwork
  • 30,549
  • 7
  • 101
  • 91
-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 ;)