Bash printf Command
Updated on
•7 min read

When writing Bash scripts, еcho 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:
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
argumentsthan format specifiers are provided, theformatstring is reused to consume all of the arguments. - If fewer
argumentsthan 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
printfcommand. - 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:
printf "Open issues: %s\nClosed issues: %s\n" "34" "65"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:
%[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.%xprints lower-case letters and%Xprints upper-case.%e,%E- Print the argument as a floating-point number in exponential notation.%eprints lower-case letters and%Eprints upper-case.%a,%A- Print the argument as a floating-point number in hexadecimal fractional notation.%aprints lower-case letters and%Aprints 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.%gprints lower-case letters and%Gprints 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):
printf "Decimal: %d\nHex: %x\nOctal: %o\n" 100 100 100Decimal: 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’s padded with spaces. The width can be specified as a non-negative decimal integer or an asterisk (*).
Here is an example:
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).
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 precede the argument that’s being formatted.
In the example below, we’re setting the width to 10:
printf "%0*d" 10 50 is a flag that pads the number with leading zeros instead of blanks. The output text will have at least 10 characters:
0000000005
Precision directive
The .precision modifier consists of a dot (.) followed by a positive integer or asterisk (*) that 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:
printf "%.3f" 1.618033981.618
When precision is set to an asterisk (*), its value is set by the precision argument that precede the argument that’s being formatted.
printf "%.*f" 3 1.618033981.618
Practical Tips
- Always use quotes around the format string to prevent unwanted globbing or variable expansion.
- Prefer single quotes for literal formats unless you need variable expansion inside the format itself.
Conclusion
The printf builtin command is a powerful and predictable alternative to echo. It takes a format and arguments and prints a clean, aligned, and professional output.
If you have any questions or feedback, feel free to leave a comment.


