Home / Alt manpages / printf(1)

  • printf(1)
  • User command
  • linux

Use GNU printf for Predictable Shell Output

You will finish with a reliable way to print text, numbers and generated shell output from GNU printf, including repeated arguments and controlled spacing. The examples use GNU coreutils 9.4, installed here as package version 9.4-3ubuntu6.3.

Allow about ten minutes. You need a shell and a normal user account. These examples only write to standard output, so they do not need sudo and do not alter files or services. Use /usr/bin/printf when you want to test the external GNU program specifically. A shell may provide its own printf builtin with a different set of extensions.

1. Confirm which printf you are using

Check the command path and installed version before putting syntax into a script:

$ command -v printf
/usr/bin/printf
$ /usr/bin/printf --version | head -n 1
printf (GNU coreutils) 9.4

command -v may report a shell builtin rather than a path. That is normal. For portable shell scripts, printf is usually preferable to echo, because echo implementations disagree about options and backslash escapes. For this guide, the explicit path makes the GNU behaviour unambiguous.

Checkpoint

If /usr/bin/printf --version does not report GNU coreutils, stop and read that system's manual before copying the GNU-specific examples such as %q.

2. Print literal text and values

The first argument is the format. A %s conversion consumes the next argument as text, and \n adds a newline:

$ /usr/bin/printf 'user=%s\nstatus=%s\n' 'Ada' 'ready'
user=Ada
status=ready

Keep the format in single quotes when it contains backslashes or dollar signs. Quote values separately. This prevents whitespace and shell metacharacters in a value from changing how the shell parses the command.

The format can be reused. With three values and one conversion, GNU printf repeats the format until all arguments are consumed:

$ /usr/bin/printf 'item=%s\n' 'red' 'green' 'blue'
item=red
item=green
item=blue

With too few arguments, text conversions receive an empty string and numeric conversions receive zero. That default can hide a missing variable, so make required inputs explicit in a script rather than trusting the output.

3. Format numbers and columns

Use numeric conversions when the input is meant to be a number. The common forms include %d for decimal integers, %f for floating-point values, and %x for hexadecimal:

$ /usr/bin/printf 'count=%d hex=%x rate=%.2f%%\n' 27 27 3.5
count=27 hex=1b rate=3.50%

The doubled %% prints one literal percent sign. The .2 precision limits the fractional part here. GNU printf converts arguments to the requested type, but invalid numeric input is an error condition worth checking in a script.

A field width pads output to a minimum size. A star takes the width from the next argument, which is useful when the width is calculated:

$ /usr/bin/printf '%*s %s\n' 8 'ok' 'connected'
      ok connected

The padding is spaces by default. A negative width makes the field left-aligned. Keep the format and width under your control; do not treat an untrusted value as a format string.

4. Use escapes deliberately

GNU printf interprets escapes in the format, including \t for a tab, \n for a newline, and hexadecimal or Unicode forms. This is useful for small, known strings:

$ /usr/bin/printf 'name\tstate\n%s\t%s\n' 'worker-1' 'ready'
name	state
worker-1	ready

For a value containing escapes, use %b. It interprets backslash escapes in that value, so only use it when the value is trusted or deliberately constructed by your script:

$ /usr/bin/printf '%b\n' 'first\nsecond'
first
second

Do not use %b as a way to print arbitrary user input. A value containing \c can suppress the rest of the output, and other escapes can create control characters. For ordinary data, %s is the safer choice.

5. Quote a value for later shell input

GNU's %q conversion prints a value in a form that can be reused as shell input. It is useful for diagnostics and for inspecting a value without losing its spaces:

$ /usr/bin/printf 'value=%q\n' 'two words; keep this'
value='two words; keep this'

This output is shell-quoted, not a general-purpose data format. Do not pass untrusted generated text to eval merely because it came from %q. Prefer arrays and direct command arguments when a script needs to run a command. The conversion is also a GNU extension, so do not assume it exists in another implementation.

6. Avoid the two common traps

First, never put a variable in the format position when it may contain percent signs:

$ message='100% ready'
$ /usr/bin/printf '%s\n' "$message"
100% ready

The fixed %s format prints the value literally. Using printf "$message\n" would let the value become formatting instructions.

Second, remember that shell redirection changes files before printf runs. This is destructive if the destination already contains useful data:

$ /usr/bin/printf '%s\n' 'new line' > output.txt

For a new file, that is fine. To append instead, use >>. To replace a file safely, write a new temporary file, check it, then rename it in the same directory. If you accidentally truncate a file, stop writing to it and restore it from your normal backup; printf cannot undo shell redirection.

Done means

  • You confirmed whether the shell selected a builtin or GNU coreutils 9.4.
  • You use a fixed format with quoted values, especially for data containing spaces or percent signs.
  • You know that a format is reused for extra arguments and that missing arguments become empty text or zero.
  • You reserve %b for deliberately trusted escape sequences and treat %q as GNU-specific shell quoting.
  • You checked the redirection target before allowing output to replace or append to a file.