Linux Basics: Format Bash Output with printf
Predictable output helps both people and downstream tools. Keep the format string fixed, then pass values as quoted arguments.
These examples were tested on Linux with GNU Bash 5.2.37. Use Bash rather than sh. No packages or administrator access are needed.
Prepare a scratch directory
You need Bash, a text editor, and the mktemp, rm, and rmdir utilities. Keep using the same terminal. Save each named source file in this scratch directory before running its command. Calling bash explicitly avoids changing executable permissions.
start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 11. Print text without interpreting its contents
Save this as printf-literal.sh:
#!/usr/bin/env bash
message='Progress: 100% ready; path C:\tmp'
printf '%s\n' "$message"
printf 'Complete: %d%%\n' 100Run it:
bash printf-literal.shOutput:
Progress: 100% ready; path C:\tmp
Complete: 100%Use %s for data rather than putting a variable in the format position. A literal percent sign in the format is %%. Backslashes in the value remain ordinary text with %s.
2. Align a compact report
Save this as printf-columns.sh:
#!/usr/bin/env bash
export LC_ALL=C
printf '%-10s %5s %7s\n' Item Count Price
printf '%-10s %5d %7.2f\n' apples 3 1.5 pears 12 2.25Run it:
bash printf-columns.shOutput:
Item Count Price
apples 3 1.50
pears 12 2.25A minus sign left-aligns a field; other fields here are right-aligned. Width is a minimum, not a truncation limit. .2 displays two fractional digits, and the format repeats for the next set of arguments. The locale fixes the decimal separator.
3. Build a label without a subprocess
Save this as printf-variable.sh:
#!/usr/bin/env bash
printf -v label 'batch-%04d' 23
printf 'Label: %s\n' "$label"
path='reports/weekly notes.txt'
printf 'Bash-escaped path: %q\n' "$path"Run it:
bash printf-variable.shOutput:
Label: batch-0023
Bash-escaped path: reports/weekly\ notes.txtBash printf -v assigns formatted text directly to a variable. %04d pads a decimal integer with zeros. %q produces Bash-reusable quoting for inspection; it is not JSON, a URL encoder, or a reason to evaluate untrusted text.
Clean up
In the same terminal, remove only the example files, return to your original directory, and remove the empty scratch directory:
rm -- printf-literal.sh printf-columns.sh printf-variable.sh
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dirReference
See the GNU Bash manual: Bash Builtins for the relevant shell behavior. The installed Bash help command also documents these builtins.
Acknowledgements
This post was created with assistance from AI.