94

I'm writing a bash script to get some podcasts. The problem is that some of the podcast numbers are one digits while others are two/three digits, therefore I need to pad them to make them all 3 digits.

I tried the following:

n=1

n = printf %03d $n

wget http://aolradio.podcast.aol.com/sn/SN-$n.mp3

but the variable 'n' doesn't stay padded permanently. How can I make it permanent?

8 Answers8

129

Use command substitution to assign the result of the printf command:

n=1
wget http://aolradio.podcast.aol.com/sn/SN-$(printf %03d $n).mp3

EDIT: Note that I removed one line which was not really necessary. If you want to assign the output of 'printf %...' to n, you could use

n=$(printf %03d $n)

and after that, use the $n variable substitution you used before.

Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
ChristopheD
  • 112,638
  • 29
  • 165
  • 179
  • 7
    Why not: `wget $(printf http://aolradio.podcast.aol.com/sn/SN-%03d $n.mp3, $n)`. Just put the whole URL in the `printf` statement. – David W. Jun 16 '14 at 01:43
  • What if you actually need to pad a string? for example, I have the string "Hello" but I need to always print 10 characters, I would need to print the string: "-----Hello" or if I have "yes" I still get 10 characters printed as: "-------yes" – m4l490n Jan 17 '19 at 18:22
49

Seems you're assigning the return value of the printf command (which is its exit code), you want to assign the output of printf.

bash-3.2$ n=1
bash-3.2$ n=$(printf %03d $n)
bash-3.2$ echo $n
001
vidstige
  • 12,492
  • 9
  • 66
  • 110
nos
  • 223,662
  • 58
  • 417
  • 506
24

Attention though if your input string has a leading zero!
printf will still do the padding, but also convert your string to hex octal format.

# looks ok
$ echo `printf "%05d" 03`
00003

# but not for numbers over 8
$ echo `printf "%05d" 033`
00027

A solution to this seems to be printing a float instead of decimal.
The trick is omitting the decimal places with .0f.

# works with leading zero
$ echo `printf "%05.0f" 033`
00033

# as well as without
$ echo `printf "%05.0f" 33`
00033
UnSandpiper
  • 526
  • 6
  • 8
20

to avoid context switching:

a="123"
b="00000${a}"
c="${b: -5}"
cC Xx
  • 301
  • 2
  • 2
4
n=`printf '%03d' "2"`

Note spacing and backticks

3

As mentioned by noselad, please command substitution, i.e. $(...), is preferable as it supercedes backtics, i.e. `...`.

Much easier to work with when trying to nest several command substitutions instead of escaping, i.e. "backslashing", backtics.

Camilo Martin
  • 37,236
  • 20
  • 111
  • 154
Rob Wells
  • 36,220
  • 13
  • 81
  • 146
0

This is in response to an answer given by cC Xx. It will work only until a's value less is than 5 digits.

Consider when a=12345678. It'll truncate the leading digits:

a="12345678" 
b="00000${a}" 
c="${b: -5}" 
echo "$a, $b, $c"

This gives the following output:

12345678, 0000012345678, 45678

Putting an if to check value of a is less than 5 digits and then doing it could be solution:

if [[ $a -lt 9999 ]] ; then b="00000${a}" ; c="${b: -5}" ;  else c=$a; fi  
fcdt
  • 2,371
  • 5
  • 14
  • 26
Siva
  • 21
  • 1
  • 5
  • Putting an if to check value of a is less than 5 digits and then doing it could be solution. – Siva Oct 17 '20 at 17:02
0

Just typing this here for additional information.

If you know the number of zeroes you need, you can use the string concatenation:

let pad="0"
pad+=1
echo $pad # this will print 01