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.
The route
Jump straight to the step you need, or tick off Done means at the end.
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
%bfor deliberately trusted escape sequences and treat%qas GNU-specific shell quoting. - You checked the redirection target before allowing output to replace or append to a file.