242

I have a basic number for loop which increments the variable num by 1 over each iteration...

for (( num=1; num<=5; num++ )) do echo $num done 

Which outputs:

1 2 3 4 5 

I'm trying to make it produce the output (add leading zero before $num):

01 02 03 04 05 

Without doing:

echo 0$num 
7
  • 5
    Use printf with an appropriate format. Commented Aug 27, 2013 at 8:04
  • 3
    printf from bash has many bad effect, i prefer use awk as following: "num=$(echo $num | awk '{printf("%02d", $1)}'" Commented Aug 27, 2013 at 8:41
  • @binogure Just a heads up: Awk has different behavior on different systems. There's mawk, gawk, awk, nawk, etc. I try not to recommend it because it seems like I can only test it on the computer I'm writing it on. Perl/Ruby are more compatible. Commented Aug 27, 2013 at 9:43
  • 5
    printf '%s\n' {01..05}. Commented Feb 5, 2015 at 18:18
  • stackoverflow.com/a/18469460/188159 should be set as the answer. Commented Apr 20, 2015 at 3:49

7 Answers 7

433

Use the following syntax:

$ for i in {01..05}; do echo "$i"; done 01 02 03 04 05 

Disclaimer: Leading zeros only work in >=bash-4.

If you want to use printf, nothing prevents you from putting its result in a variable for further use:

$ foo=$(printf "%02d" 5) $ echo "${foo}" 05 
Sign up to request clarification or add additional context in comments.

8 Comments

Unfortunately the {01..05} doesn't work for older versions of bash. I'm on a server with bash 3.2.51 and that will print the numbers without leading zeroes. On my desktop with 4.2.37 it does work well though.
doesn't work for e.g. {01..10} though
@Matt What exactly does not work? As long as you have a recent enough version of bash this works fine.
@SRG seq can do the padding itself if you want to pad to the widest numbers width using -w, besides that your example is invalid as it misses the do. Here is how you can do it: for i in `seq -w 1 50`; do echo $i; done
@Vampire I cannot edit my comment to fix the missing do, but thanks for the alternative, sounds interesting!
|
86

seq -w will detect the max input width and normalize the width of the output.

for num in $(seq -w 01 05); do ... done 

At time of writing this didn't work on the newest versions of OSX, so you can either install macports and use its version of seq, or you can set the format explicitly:

seq -f '%02g' 1 3 01 02 03 

But given the ugliness of format specifications for such a simple problem, I prefer the solution Henk and Adrian gave, which just uses Bash. Apple can't screw this up since there's no generic "unix" version of Bash:

echo {01..05} 

Or:

for number in {01..05}; do ...; done 

11 Comments

Just fyi seq is not present on OSX
It's on my machine (OS X 10.7.5). The man page only dates to 2010, so it looks to be a (relatively) recent addition.
doesnt work on mac os sierra for 01 to 05. but works for 01 to 10.
Try giving seq a format string. seq -f '%02g' 1 5
seq -w really does the job without clutter!
|
59

Use printf command to have 0 padding:

printf "%02d\n" $num 

Your for loop will be like this:

for (( num=1; num<=5; num++ )); do printf "%02d\n" $num; done 01 02 03 04 05 

3 Comments

I'm not interested in outputting it to the screen (that's what printf is mainly used for, right?) The variable $num is going to be used as a parameter for another program but let me see what I can do with this.
Please explain clearly what you are trying to do than I can suggest a better suited answer.
@BruceBlacklaws printf in the shell is used for creating strings from a list of arguments. Output to screen is just the default. In fact, shell pipelines are the ultimate example of functional programming -- just input, output, no side-effects. ;-)
32

I'm not interested in outputting it to the screen (that's what printf is mainly used for, right?) The variable $num is going to be used as a parameter for another program but let me see what I can do with this.

You can still use printf:

for num in {1..5} do value=$(printf "%02d" $num) ... Use $value for your purposes done 

1 Comment

This works but spawning subshell is expensive. For big sequences it may take very long time.
14

From bash 4.0 onward, you can use Brace Expansion with fixed length strings. See below for the original announcement.

It will do just what you need, and does not require anything external to the shell.

$ echo {01..05} 01 02 03 04 05 for num in {01..05} do echo $num done 01 02 03 04 05 

CHANGES, release bash-4.0, section 3

This is a terse description of the new features added to bash-4.0 since the release of bash-3.2.

. . .

z. Brace expansion now allows zero-padding of expanded numeric values and will add the proper number of zeroes to make sure all values contain the same number of digits.

2 Comments

I know I did not specify which version of BASH and what platform it's running on but this flat fails on GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16)
@BruceBlacklaws Correct. The fixed length numbers were added in 4.0. Included the restriction.
11

why not printf '%02d' $num? See help printf for this internal bash command.

Comments

3

Just a note: I have experienced different behaviours on different versions of bash:

  • version 3.1.17(1)-release-(x86_64-suse-linux) and
  • Version 4.1.17(9)-release (x86_64-unknown-cygwin))

for the former (3.1) for nn in (00..99) ; do ... works but for nn in (000..999) ; do ... does not work both will work on version 4.1 ; haven't tested printf behaviour (bash --version gave the version info)

Cheers, Jan

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.