Bash printf Command

By 

Updated on

8 min read

bash printf command formatting output in a Linux terminal

When writing Bash scripts, echo is commonly used for printing to standard output. While simple and convenient, echo is limited in its capabilities and formatting control.

To have more control over the output formatting, use the printf command instead.

The printf command behaves similarly to the C printf() function and gives you more control over formatting.

The printf Command

printf is a shell builtin in Bash and in other popular shells like Zsh and Ksh. There is also a standalone /usr/bin/printf binary, but the shell built-in version takes precedence.

We will cover the Bash builtin version of printf.

The syntax for the printf command is as follows:

txt
printf [-v var] format [arguments...]

The -v option tells printf not to print the output but to assign it to the variable (var).

The format is a string that may contain three different types of objects:

  • Regular characters are printed to the output as-is.
  • Backslash-escaped characters are interpreted and then printed.
  • Conversion specifiers that describe the format and are replaced by the values of respective arguments that follow the format string.

arguments are values that replace the specifiers in the format string.

The command accepts any number of arguments.

  • If more arguments than format specifiers are provided, the format string is reused to consume all of the arguments.
  • If fewer arguments than format specifiers are supplied, the extra numeric-format specifiers are set to zero value, while string-format specifiers are set to a null string.

Below are a few points to consider when passing arguments to the printf command:

  • The shell will expand all variables, perform wildcard matching, and handle special characters before passing the arguments to the printf command.
  • When using single quotes '', the literal value of each character enclosed within the quotes will be preserved. Variables and commands will not be expanded.

Unlike echo, the printf command does not automatically add a newline character (\n) at the end of the line. You must include \n explicitly.

A typical example of using printf looks like:

Terminal
printf "Open issues: %s\nClosed issues: %s\n" "34" "65"
output
Open issues: 34
Closed issues: 65

The string Open issues: %s\nClosed issues: %s\n is the format, while “34” and “65” are arguments. The format string contains two newline characters (\n) and two format specifiers (%s) that are replaced with the arguments.

Backslash Escapes

The backslash-escaped characters are interpreted when used in the format string or in an argument corresponding to a %b conversion specifier. Here is a list of the most common escape characters:

  • \\ - Displays a backslash character.
  • \b - Displays a backspace character.
  • \n - Displays a new line.
  • \r - Displays a carriage return.
  • \t - Displays a horizontal tab.
  • \v - Displays a vertical tab.

Conversion Specifiers

A conversion specification takes the following form:

txt
%[flags][width][.precision]specifier

Each conversion specification starts with the percent sign (%), includes optional modifiers, and ends with one of the following letters that represent the data type (specifier) of the corresponding argument: aAbcdeEfgGioqsuxX.

Type conversion specifier

The type conversion specifier is a character that specifies how to interpret the corresponding argument. This character is required and is placed after the optional fields.

Below is a list showing all type conversions and what they do:

  • %b - Print the argument while expanding backslash escape sequences.
  • %q - Print the argument shell-quoted, reusable as input.
  • %d, %i - Print the argument as a signed decimal integer.
  • %u - Print the argument as an unsigned decimal integer.
  • %o - Print the argument as an unsigned octal integer.
  • %x, %X - Print the argument as an unsigned hexadecimal integer. %x prints lower-case letters and %X prints upper-case.
  • %e, %E - Print the argument as a floating-point number in exponential notation. %e prints lower-case letters and %E prints upper-case.
  • %a, %A - Print the argument as a floating-point number in hexadecimal fractional notation. %a prints lower-case letters and %A prints upper-case.
  • %g, %G - Print the argument as a floating-point number in normal or exponential notation, whichever is more appropriate for the given value and precision. %g prints lower-case letters and %G prints upper-case.
  • %c - Print the argument as a single character.
  • %f - Print the argument as a floating-point number.
  • %s - Print the argument as a string.
  • %% - Print a literal % symbol.

An unsigned number represents zero and positive numbers, while a signed number represents negative, zero, and positive numbers.

The following command prints the number 100 in three different numeral systems (Multiple bases):

Terminal
printf "Decimal: %d\nHex: %x\nOctal: %o\n" 100 100 100
output
Decimal: 100
Hex: 64
Octal: 144

Flags directive

Flags are the first optional modifiers and are used to set the justification, leading zeros, prefixes, etc.

Here are the most common ones:

  • - - Left-align the printed text within the field. By default, the text is right-aligned.
  • + - Prefix the numbers with a + or - sign. By default, only negative numbers are prefixed with a negative sign.
  • 0 - Pads numbers with leading zeros rather than spaces.
  • blank - Prefix the positive numbers with a blank space and negative numbers with a minus (-).
  • # - An alternative format for numbers.

Width directive

The width directive field, placed after any flag characters, specifies the minimum number of characters the conversion should produce.

If the output text width is less than the specified width, it is padded with spaces. The width can be specified as a non-negative decimal integer or an asterisk (*).

Here is an example:

Terminal
printf "%20s %d\n" Mark 305

%20s means set the field to at least 20 characters long. Blanks are added before the text because, by default, the output is right-justified. To align the text to the left, use the - flag (%-20s).

output
      Mark 305

When an asterisk (*) is used as a width directive, then the width of the conversion field is set by a width argument that precedes the argument that’s being formatted.

In the example below, we’re setting the width to 10:

Terminal
printf "%0*d" 10 5

0 is a flag that pads the number with leading zeros instead of blanks. The output text will have at least 10 characters:

output
0000000005

Precision directive

The .precision modifier consists of a dot (.) followed by a positive integer or asterisk (*) which, depending on the specifier type, sets the number of string or digit characters or the number of decimal places to be printed.

The precision has the following effect:

  • If the conversion type is an integer, the precision specifies the minimum number of digits to be printed. If the number of digits in the argument is less than the precision, leading zeros are printed.
  • If the conversion type is floating-point, the precision specifies the number of digits after the decimal point. The default precision is 6.
  • If the conversion type is a string, the precision specifies the maximum number of characters to be printed. If the number of characters in the argument is greater than the precision, the excess characters are truncated.

Here is an example showing how to round a floating-point number to 3 decimals:

Terminal
printf "%.3f" 1.61803398
output
1.618

When precision is set to an asterisk (*), its value is set by the precision argument that precedes the argument being formatted.

Terminal
printf "%.*f" 3 1.61803398
output
1.618

Practical Tips

  • Always quote the format string to prevent unwanted globbing or variable expansion.
  • Prefer single quotes for literal formats unless you need variable expansion inside the format string itself.
  • Use printf -v var format args to store formatted output in a variable instead of printing it.
  • Use \n explicitly to end lines — unlike echo, printf does not add a newline automatically.
  • To print a literal %, use %%.

Quick Reference

Format / OptionDescription
%sString
%d / %iSigned decimal integer
%fFloating-point number
%e / %EFloating-point in exponential notation
%oOctal integer
%x / %XHexadecimal integer
%cSingle character
%%Literal %
%bString with backslash escapes expanded
%NsRight-align string in field of width N
%-NsLeft-align string in field of width N
%.NfFloat with N decimal places
%0NdInteger padded with leading zeros to width N
-v varStore output in variable instead of printing

FAQ

What is the difference between printf and echo in Bash? echo is simpler but inconsistent across shells — its handling of escape sequences and the -e flag varies. printf behaves consistently, supports precise formatting with conversion specifiers, does not add a trailing newline unless you include \n, and works the same way across Bash, Zsh, and Ksh.

Why does my printf output appear on one line with no newlines? printf does not add a newline at the end of output automatically. Add \n in the format string wherever you need a line break: printf "line one\nline two\n".

How do I store printf output in a variable? Use the -v flag: printf -v myvar "Hello, %s" "$name". This assigns the formatted string to myvar without printing it. It is faster than using a subshell with myvar=$(printf ...).

Can printf repeat a format string for multiple arguments? Yes. If you provide more arguments than format specifiers, printf reuses the format string until all arguments are consumed. For example, printf "%s\n" one two three prints each word on its own line.

Conclusion

printf is the reliable choice when output formatting matters in a Bash script. Use %s for strings, %d for integers, %f for floats, and width and precision modifiers to align tabular output. For a broader look at printing in Bash, see the echo command guide .

Tags

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page