Bash printf Command with Examples

The Bash printf command is a versatile utility that offers fine-grained control over output formatting. Derived from the C programming language, printf in Bash is a built-in feature often taking precedence over its standalone binary counterpart.

Key Features of Bash printf Command

  • Precision Control: Unlike the simpler echo command, printf allows meticulous output control, including field width and padding.
  • Format String: The command uses a format string containing various characters and specifiers, offering extensive customization.
  • Argument Flexibility: printf can handle multiple arguments, recycling the format string when the number of arguments exceeds the format specifiers.
  • Wide Applications: From simple text output to complex tables and dynamic progress bars, printf’s applications are diverse.

The Bash printf command is an essential tool for anyone working with Bash scripts, offering a level of control that more straightforward commands can’t match. Our upcoming article will explore practical examples to help you master this powerful Bash command.

Understanding the Bash printf Command

Syntax of the printf Command

The syntax for the printf command is as follows:

printf [-v var] format [arguments]

The -v option instructs printf not to print the output but to assign it to the variable. The format is a string which may contain three different types of objects:

  • Normal characters that are printed to the output as-is.
  • Backslash-escaped characters, which are interpreted and then printed.
  • Conversion specifications that describe the format are replaced by the values of respective arguments that follow 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 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 null string.

Considerations When Passing Arguments to the bash printf Command

When passing arguments to the printf command, there are a few points to consider:

  • The shell will substitute all variables, wildcard matching, and 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.

A typical example of using printf looks like:

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

This will output:

Open issues: 34
Closed issues: 65

In this example, 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.

It’s important to note that the printf command doesn’t add a newline character (\n) at the end of the line. This is a key difference from the echo command that adds a newline character by default.

Backslash-Escaped Characters

The backslash-escaped characters are interpreted when used in the format string or 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 Specifications

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 representing the data type (specifier) of the corresponding argument: aAbcdeEfgGioqsuxX.

Understanding Conversion Specifiers with bash printf Command

The type conversion specifier is a character that specifies how to interpret the corresponding argument. This character is required, and it is placed after the optional fields. Here is a list showing all types of 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.

For example, the following command prints the number 100 in three different number systems:

printf "Decimal: %d\nHex: %x\nOctal: %o\n" 100 100 100

This will output:

Decimal: 100
Hex: 64
Octal: 144

Flags Directive with bash printf Command

Flags are the first optional modifiers 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 - signs. By default, only negative numbers are prefixed with a negative sign.
  • 0 – Pads numbers with leading zeros rather than space.
  • blank – Prefix the positive numbers with a blank space and negative numbers with a minus (-).
  • # – An alternative format for numbers.

Width Directive with bash printf Command

The width directive field is placed after flag characters and specifies the minimum number of characters the conversion should result in. If the outputted text width exceeds 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 at least 20 characters long. Blanks are added before the text because, by default, the output is right-justified. To align the text to left, use the - flag (%-20s). The output will be:

                 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:

printf "%0*d" 10 50

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

0000000050

Precision Directive with bash printf Command

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 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 precision, leading zeros are printed.
  • If the conversion type is a floating-point, the precision specifies the number of digits that follow the decimal-point character. The default precision is 6.
  • If the conversion type is a string, the precision specifies the maximum number of characters to be printed. The excess characters are truncated if the number of characters in the argument exceeds precision.

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

printf "%.3f" 1.61803398

This will output:

1.618

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

printf "%.*f" 3 1.61803398

This will also output:

1.618

Basic Examples of Bash printf Command

Now that we have covered the basics of the printf command, let’s look at some examples of how to use it. These examples will help you understand how to use the printf command effectively in your bash scripts.

Example 1: Printing a Simple Text with bash printf Command

You can use printf to print a simple text. For example:

printf "Hello, World!\n"

This will output:

Hello, World!

In this example, Hello, World!\n is the format string. The \n at the end of the format string is a newline character that causes the cursor to move to the beginning of the next line.

Example 2: Printing a Variable with bash printf Command

You can also use printf to print the value of a variable. For example:

name="John Doe"
printf "Hello, %s!\n" "$name"

This will output:

Hello, John Doe!

In this example, %s is a format specifier that gets replaced by the value of the name variable.

Example 3: Printing Multiple Variables with bash printf Command

The printf command can also print multiple variables. For example:

first_name="John"
last_name="Doe"
printf "Hello, %s %s!\n" "$first_name" "$last_name"

This will output:

Hello, John Doe!

In this example, the first %s gets replaced by the value of the first_name variable and the second %s gets replaced by the value of the last_name variable.

Example 4: Formatting Numbers with bash printf Command

The printf command can also be used to format numbers. For example:

num=5
printf "You have %02d new messages.\n" "$num"

This will output:

You have 05 new messages.

In this example, %02d is a format specifier that gets replaced by the value of the num variable. The 02 in %02d specifies that the number should be printed with at least 2 digits, and leading zeros should be added if necessary.

Advanced Examples of Bash printf Command

Now that we’ve covered some basic examples, let’s move on to some more advanced uses of the printf command.

Example 1: Printing a Table with bash printf Command

You can use printf to print a table of data. For example:

printf "%-10s %-8s %-4s\n" Name Age Rating
printf "%-10s %-8s %-4.2f\n" John 35 4.53
printf "%-10s %-8s %-4.2f\n" Alice 37 3.89
printf "%-10s %-8s %-4.2f\n" Bob 29 4.98

In this example, we use the - flag to left-align the text and specify a width for each column.

Example 2: Printing a Calendar with bash printf Command

You can use printf to print a calendar. For example:

printf "     March 2023\n"
printf "Su Mo Tu We Th Fr Sa\n"
printf "          1  2  3  4\n"
printf " 5  6  7  8  9 10 11\n"
printf "12 13 14 15 16 17 18\n"
printf "19 20 21 22 23 24 25\n"
printf "26 27 28 29 30 31\n"

This will output:

     March 2023
Su Mo Tu We Th Fr Sa
          1  2  3  4
 5  6  7  8  9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

In this example, we use printf to print each line of the calendar.

Example 3: Printing a Progress Bar with bash printf Command

You can use printf to print a progress bar. For example:

total=10
for i in $(seq 1 $total); do
    printf "\rProgress: [%-10s] %d%%" $(repeat $i "#") $(($i * 10))
    sleep 1
done
printf "\n"

This will output a progress bar that fills up over 10 seconds:

Progress: [##########] 100%

In this example, we use a loop to update the progress bar every second. We use the - flag to left-align the text and specify a width for the progress bar.

Best Practices for Using Bash printf Command

When using the printf command in your bash scripts, there are a few best practices you should follow:

  • Always use double quotes around the format string and the arguments. This will prevent unexpected behavior if the format string or the arguments contain spaces or special characters.
  • Always use the -v option to store the output of the printf command in a variable if you plan to use it later in your script. This is more efficient than using command substitution.
  • Always specify a format for each argument. If you don’t, printf will reuse the format string for each argument, which may not be what you want.
  • Be careful when using backslash escapes in the format string. Some backslash escapes, like \n for a newline, are interpreted by printf, but others are not. If you need to use a backslash in the format string, use \\.
  • When printing a table of data, use the - flag to left-align the text and specify a width for each column. This will make the table easier to read.
  • When printing numbers, use the appropriate format specifier (%d for integers, %f for floating-point numbers, etc.) and specify a width and precision if necessary. This will make the numbers easier to read.
  • When printing a progress bar or a similar dynamic output, use the \r backslash escape to move the cursor to the beginning of the line. This will allow you to update the output in place.
  • If you’re printing a complex format, consider breaking it up into multiple printf commands. This will make your script easier to read and maintain.
  • Always test your printf commands to make sure they produce the expected output. If you’re unsure what a printf command will do, try it out in a terminal before adding it to your script.
  • Finally, remember that printf is a powerful command that can do much more than just print text. You can use it to format and print data in various ways, so don’t be afraid to experiment and learn more about its capabilities.

Wrapping Up

In this guide, we delved into the printf command in Bash, a powerful tool for formatting and printing data. We explored its syntax, the use of backslash-escaped characters, conversion specifications, and flags. We also examined a variety of practical examples, from printing simple text and variables to creating tables and progress bars. The printf command’s flexibility and control over output formatting make it an essential tool in any Bash scripter’s toolkit. As a final recommendation, always remember to use double quotes around your format strings and arguments to prevent unexpected behavior, and consider using the -v option to store printf output for later use in your scripts.