33

What's the best way to pad numbers when printing output in bash, such that the numbers are right aligned down the screen. So this:

00364.txt with 28 words in 0m0.927s
00366.txt with 105 words in 0m2.422s
00367.txt with 168 words in 0m3.292s
00368.txt with 1515 words in 0m27.238

Should be printed like this:

00364.txt with   28 words in 0m0.927s
00366.txt with  105 words in 0m2.422s
00367.txt with  168 words in 0m3.292s
00368.txt with 1515 words in 0m27.238

I'm printing these out line by line from within a for loop. And I will know the upper bound on the number of words in a file (just not right now).

nedned
  • 3,552
  • 8
  • 38
  • 41

5 Answers5

50

For bash, use the printf command with alignment flags.

For example:

printf '..%7s..' 'hello'

Prints:

..  hello..

Now, use your discretion for your problem.

Beweeted
  • 319
  • 2
  • 7
SuPra
  • 8,488
  • 4
  • 37
  • 30
  • Wow, ok that was pretty easy. I should have just RTFM. I guess I just incorrectly assumed it would be harder than that in bash. Thanks! – nedned Jun 15 '09 at 04:21
  • To remove the hard-coded "7" and **calculate the padding automatically**, see my answer below. – Jonathan Cross Apr 28 '16 at 19:48
  • The OP specifically asked for right-alignment. But you can also left-align rather than right-align with `printf '..%-7s..' 'hello'`. – mightypile May 18 '22 at 20:08
26

Here's a little bit clearer example:

#!/bin/bash
for i in 21 137 1517
do
    printf "...%5d ...\n" "$i"
done

Produces:

...   21 ...
...  137 ...
... 1517 ...
Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
11

If you are interested in changing width dynamically, you can use printf's '%*s' feature

printf '%*s' 20 hello

which prints

               hello
test30
  • 3,496
  • 34
  • 26
  • 2
    "dynamically", well, this is shell so I don't see how that's different from `printf "%${count}d" hello` – Camilo Martin Jan 27 '15 at 06:30
  • This is the best answer here, because '%*s' takes into account the length of the string. If you do `printf '%*s' $(tput cols) hello`, hello will be printed at the far edge of the terminal window. – Jonah Jan 05 '18 at 18:10
5

Here is a combination of answers above which removes the hard-coded string length of 5 characters:

VALUES=( 21 137 1517 2121567251672561 )
MAX=1

# Calculate the length of the longest item in VALUES
for i in "${VALUES[@]}"; do
  [ ${#i} -gt ${MAX} ] && MAX=${#i}
done

for i in "${VALUES[@]}"; do
  printf "... %*s ...\n" $MAX "$i"
done

Result:

...               21 ...
...              137 ...
...             1517 ...
... 2121567251672561 ...
Jonathan Cross
  • 675
  • 8
  • 17
0

If you happen to get the number to be formatted from output of another script and you wish to pipe this result to be right align, just utilize xargs:

ls -1 | wc -l | xargs printf "%7d"
Thomas Urban
  • 4,649
  • 26
  • 32