Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. Shell Script Dictionary
  3. printf

printf

Since: POSIX(sh互換)

The printf command in shell scripts formats and outputs strings, integers, floating-point numbers, and more using a format string. Unlike echo, it does not automatically append a newline, giving you complete control over the output. In addition to format specifiers such as %s, %d, %f, and %x, you can specify field widths and precision for padding and alignment. Because printf is defined by POSIX, the same syntax works across bash, sh, and zsh, making it especially useful when writing portable scripts.

printf vs echo

echo automatically appends a newline at the end, but its option behavior varies between shells and implementations. printf, on the other hand, fully specifies the output via the format string, offering superior portability and consistency.

Comparisonechoprintf
Trailing newlineAdded automatically.Not added. Control it by including \n in the format string.
Escape sequencesBehavior varies by shell and options (e.g., whether -e is supported).Always interprets \n, \t, \\, and other escapes in the format string.
Format specifiersNot supported.Supports %s, %d, %f, etc. to specify type and width.
PortabilityThe behavior of -e and -n is implementation-dependent.POSIX-compliant, so it can be used safely with sh.
Repeating with multiple argumentsConcatenates all arguments and outputs them on one line.When the number of arguments exceeds the number of format specifiers, the format string is applied repeatedly.
# echo — a newline is automatically appended
echo "碇シンジ"

# echo -n — no newline (not supported in some shells)
echo -n "碇シンジ"

# printf — control newlines explicitly with \n
printf "碇シンジ\n"

# printf — output without a trailing newline
printf "碇シンジ"

# printf — repeating the format (when there are more arguments than format variables)
#   → loops twice for "碇シンジ" and "綾波レイ"
printf "%s\n" "碇シンジ" "綾波レイ"

Format Specifiers

Format specifiers start with % and specify the type of value to output. Arguments are assigned to specifiers in the order they appear in the format string.

SpecifierTypeDescription
%sStringOutputs the argument as a string.
%dDecimal integerOutputs the argument as a signed decimal integer.
%iDecimal integerSame as %d. Also accepts hexadecimal input with a 0x prefix.
%fFloating-point numberOutputs the argument as a decimal floating-point number. Defaults to 6 decimal places.
%eScientific notationOutputs the argument in scientific notation (e.g., 1.234560e+02).
%gFloating-point (auto)Automatically switches between %f and %e based on the magnitude of the value.
%xHexadecimal (lowercase)Outputs the argument as hexadecimal using lowercase letters (af).
%XHexadecimal (uppercase)Outputs the argument as hexadecimal using uppercase letters (AF).
%oOctalOutputs the argument as an octal number.
%cCharacterOutputs only the first character of the argument.
%%Literal %Outputs a literal percent sign.
# %s — output as a string
printf "%s\n" "碇シンジ"

# %d — output as a decimal integer
printf "%d\n" 42

# %f — output as a floating-point number (6 decimal places by default)
printf "%f\n" 3.14

# %x — output as hexadecimal (lowercase)
printf "%x\n" 255     # → ff

# %X — output as hexadecimal (uppercase)
printf "%X\n" 255     # → FF

# %o — output as octal
printf "%o\n" 8       # → 10

# %% — output a literal percent sign
printf "Progress: %d%%\n" 80

Padding and Alignment

By specifying width, precision, and flags between % and the type character, you can fix the field width, set decimal precision, and align output in columns.

SyntaxDescription
%10sOutputs right-aligned in a field of 10 characters. Pads with spaces on the left.
%-10sOutputs left-aligned in a field of 10 characters. Pads with spaces on the right.
%05dOutputs with zero-padding in a field of 5 digits (e.g., 00042).
%+dOutputs positive numbers with a leading + sign.
%.2fRounds the output to 2 decimal places.
%8.2fOutputs right-aligned in a total field width of 8 characters with 2 decimal places.
%-8.2fOutputs left-aligned in a total field width of 8 characters with 2 decimal places.
%*dTakes the field width from an argument (used as printf "%*d" width value).
# Right-aligned (default) — field width 10, space-padded
printf "%10s\n" "碇シンジ"

# Left-aligned — field width 15, space-padded (- flag)
printf "%-15s\n" "惣流・アスカ・ラングレー"

# Zero-padding — integer in a field of 6 digits
printf "%06d\n" 42           # → 000042

# Force a sign on the output
printf "%+d\n" 42            # → +42
printf "%+d\n" -42           # → -42

# Fix to 2 decimal places
printf "%.2f\n" 3.14159      # → 3.14

# Total field width 8, 2 decimal places
printf "%8.2f\n" 3.14159     # →     3.14

# Left-aligned, total field width 8, 2 decimal places
printf "%-8.2f|\n" 3.14159   # → 3.14    |

Portability

printf is specified by POSIX.1, so the same syntax works across a wide range of shells including sh, dash, and zsh, not just bash. The following points summarize best practices for writing portable scripts.

TopicRecommendationReason
Outputting a newlineprintf "%s\n" "$var"echo "$var" may not recognize -e in dash or some sh implementations. Using \n with printf is the safer choice.
Escape sequencesprintf "line1\nline2\n"echo -e is not in POSIX and is implementation-dependent. printf reliably interprets \n and \t.
Strings starting with -printf "%s\n" "-n"echo -n is interpreted as an option, but with printf the value is part of the format string, so it works correctly.
%b specifierAvoid using it.%b (backslash expansion) has inconsistent behavior across non-POSIX shells.
Floating-point inputSet LC_ALL=CIn some locales the decimal separator is a comma (,), which can affect how %f parses input.
# -----------------------------------------------
#  Portable printf usage
# -----------------------------------------------

# Not recommended: echo -e behavior varies by shell
# echo -e "line1\nline2"

# Recommended: printf reliably interprets \n
printf "line1\nline2\n"

# Not recommended: echo -n is not in POSIX (may not work in some shells)
# echo -n "no newline"

# Recommended: simply omit the trailing \n in printf
printf "no newline"

# Recommended: strings starting with - are output safely
printf "%s\n" "-option-like-string"

# Recommended: use LC_ALL=C to avoid locale-dependent behavior
LC_ALL=C printf "%.2f\n" 3.14

Sample Code

eva_printf_basic.sh
#!/bin/bash
# -----------------------------------------------
#  Demonstrates the basic printf format specifiers
#  using Evangelion pilot data
# -----------------------------------------------

# -----------------------------------------------
#  Pilot data (name, unit, sync rate, ID code, serial number)
# -----------------------------------------------

#  Name                              Unit        Rate     ID  Serial
pilot1="碇シンジ";        eva1="初号機";  rate1=41.3;  id1=3;   serial1=1
pilot2="綾波レイ";        eva2="零号機";  rate2=57.2;  id2=0;   serial2=0
pilot3="惣流・アスカ・ラングレー"; eva3="弐号機";  rate3=98.0;  id3=2;   serial3=2
pilot4="渚カヲル";        eva4="第4使徒"; rate4=100.0; id4=17;  serial4=17
pilot5="真希波・マリ・イラストリアス"; eva5="仮設5号機"; rate5=77.8;  id5=5;   serial5=5

echo "=== Evangelion Pilot Database ==="
echo ""

# -----------------------------------------------
#  %s — output as a string
# -----------------------------------------------

printf "Pilot: %s\n" "${pilot1}"
printf "Pilot: %s\n" "${pilot2}"
echo ""

# -----------------------------------------------
#  %d — output as a decimal integer
# -----------------------------------------------

printf "ID (decimal): %d\n" "${id3}"
printf "ID (decimal): %d\n" "${id4}"
echo ""

# -----------------------------------------------
#  %f — output as a floating-point number (6 decimal places by default)
# -----------------------------------------------

printf "Sync rate: %f\n" "${rate1}"
echo ""

# -----------------------------------------------
#  %.2f — fix to 2 decimal places
# -----------------------------------------------

printf "Sync rate (2dp): %.2f%%\n" "${rate1}"
printf "Sync rate (2dp): %.2f%%\n" "${rate3}"
printf "Sync rate (2dp): %.2f%%\n" "${rate4}"
echo ""

# -----------------------------------------------
#  %x — output as hexadecimal (lowercase)
#  %X — output as hexadecimal (uppercase)
# -----------------------------------------------

printf "Serial (hex lower): %x\n" "${serial4}"   # 17 → 11
printf "Serial (hex upper): %X\n" "${serial4}"   # 17 → 11
printf "Serial (hex lower): %x\n" "${serial5}"   # 5  → 5
echo ""

# -----------------------------------------------
#  %% — output a literal percent sign
# -----------------------------------------------

printf "Top sync rate: %d%%\n" 100
$ chmod +x eva_printf_basic.sh
$ ./eva_printf_basic.sh
=== Evangelion Pilot Database ===

Pilot: 碇シンジ
Pilot: 綾波レイ

ID (decimal): 2
ID (decimal): 17

Sync rate: 41.300000

Sync rate (2dp): 41.30%
Sync rate (2dp): 98.00%
Sync rate (2dp): 100.00%

Serial (hex lower): 11
Serial (hex upper): 11
Serial (hex lower): 5

Top sync rate: 100%
eva_printf_padding.sh
#!/bin/bash
# -----------------------------------------------
#  Demonstrates printf padding and alignment
#  using Evangelion pilot data
# -----------------------------------------------

# -----------------------------------------------
#  Pilot list (name, unit, sync rate)
# -----------------------------------------------

declare -a pilots=("碇シンジ" "綾波レイ" "惣流・アスカ・ラングレー" "渚カヲル" "真希波・マリ・イラストリアス")
declare -a evas=("初号機" "零号機" "弐号機" "第4使徒" "仮設5号機")
declare -a rates=("41.30" "57.20" "98.00" "100.00" "77.80")
declare -a ids=(3 0 2 17 5)

echo "=== Pilot List (with alignment) ==="
echo ""

# Print the header row
# %-28s : left-aligned, 28 characters (name column)
# %-10s : left-aligned, 10 characters (unit column)
# %7s   : right-aligned, 7 characters (sync rate header)
# %5s   : right-aligned, 5 characters (ID header)
printf "%-28s %-10s %7s %5s\n" "Name" "Unit" "Rate" "ID"
printf "%-28s %-10s %7s %5s\n" "----------------------------" "----------" "-------" "-----"

# Loop over the number of array elements
for i in 0 1 2 3 4; do
    # %-28s : name, left-aligned, 28 characters
    # %-10s : unit, left-aligned, 10 characters
    # %6.2f%% : sync rate, width 6, 2 decimal places, right-aligned
    # %5d   : ID, right-aligned, 5 digits
    printf "%-28s %-10s %6.2f%% %5d\n" \
        "${pilots[$i]}" "${evas[$i]}" "${rates[$i]}" "${ids[$i]}"
done

echo ""
echo "=== Zero-padding example (serial numbers in 6 digits) ==="
echo ""

# %06d — width 6, zero-padded
for i in 0 1 2 3 4; do
    printf "Serial: %06d  Pilot: %s\n" "${ids[$i]}" "${pilots[$i]}"
done

echo ""
echo "=== Signed output (+ flag) ==="
echo ""

# %+.1f — include a + sign for positive numbers
diff_rates=("41.3" "-12.5" "98.0" "100.0" "-5.2")
for i in 0 1 2 3 4; do
    printf "  %-28s Change: %+.1f%%\n" "${pilots[$i]}" "${diff_rates[$i]}"
done
$ chmod +x eva_printf_padding.sh
$ ./eva_printf_padding.sh
=== Pilot List (with alignment) ===

名前                         搭乗機       適合率    ID
---------------------------- ---------- ------- -----
碇シンジ                     初号機       41.30%     3
綾波レイ                     零号機       57.20%     0
惣流・アスカ・ラングレー     弐号機       98.00%     2
渚カヲル                     第4使徒     100.00%    17
真希波・マリ・イラストリアス 仮設5号機    77.80%     5

=== Zero-padding example (serial numbers in 6 digits) ===

Serial: 000003  Pilot: 碇シンジ
Serial: 000000  Pilot: 綾波レイ
Serial: 000002  Pilot: 惣流・アスカ・ラングレー
Serial: 000017  Pilot: 渚カヲル
Serial: 000005  Pilot: 真希波・マリ・イラストリアス

=== Signed output (+ flag) ===

  碇シンジ                     Change: +41.3%
  綾波レイ                     Change: -12.5%
  惣流・アスカ・ラングレー     Change: +98.0%
  渚カヲル                     Change: +100.0%
  真希波・マリ・イラストリアス Change: -5.2%
eva_printf_portable.sh
#!/bin/sh
# -----------------------------------------------
#  Uses #!/bin/sh as the shebang to demonstrate
#  portable printf usage that works with POSIX sh
# -----------------------------------------------

# -----------------------------------------------
#  Pilot data (arrays are not available in sh,
#  so individual variables are used)
# -----------------------------------------------

pilot1="碇シンジ";              eva1="初号機";    rate1="41.30"
pilot2="綾波レイ";              eva2="零号機";    rate2="57.20"
pilot3="惣流・アスカ・ラングレー"; eva3="弐号機";    rate3="98.00"
pilot4="渚カヲル";              eva4="第4使徒";   rate4="100.00"
pilot5="真希波・マリ・イラストリアス"; eva5="仮設5号機"; rate5="77.80"

# -----------------------------------------------
#  Portable output patterns
#  Use printf instead of echo -e
# -----------------------------------------------

# Use printf "%s\n" to reliably append a newline
printf "%s\n" "=== NERV Pilot Emergency Bulletin ==="
printf "%s\n" ""

# Output multiple values on one line with format specifiers
# %-28s : name column (left-aligned, 28 characters)
# %s    : unit name
# %.2f  : sync rate (2 decimal places)
printf "%-28s / %s  Sync rate: %.2f%%\n" "${pilot1}" "${eva1}" "${rate1}"
printf "%-28s / %s  Sync rate: %.2f%%\n" "${pilot2}" "${eva2}" "${rate2}"
printf "%-28s / %s  Sync rate: %.2f%%\n" "${pilot3}" "${eva3}" "${rate3}"
printf "%-28s / %s  Sync rate: %.2f%%\n" "${pilot4}" "${eva4}" "${rate4}"
printf "%-28s / %s  Sync rate: %.2f%%\n" "${pilot5}" "${eva5}" "${rate5}"

printf "%s\n" ""

# -----------------------------------------------
#  Storing output in a variable
#  (printf output can be captured via command substitution)
# -----------------------------------------------

# Assemble pilot info into a single string
report=$(printf "Pilot: %-28s Unit: %s  Sync rate: %.2f%%" \
    "${pilot1}" "${eva1}" "${rate1}")

printf "%s\n" "${report}"
printf "%s\n" ""

# -----------------------------------------------
#  Safely output strings starting with -
#  echo "-option" may be misread as an option by some shells
# -----------------------------------------------

option_str="-v3.33"    # Version number string styled after Evangelion

# Potentially unsafe: echo "${option_str}"
# Safe: use printf "%s\n" to output it correctly
printf "%s\n" "${option_str}"
$ chmod +x eva_printf_portable.sh
$ ./eva_printf_portable.sh
=== NERV Pilot Emergency Bulletin ===

碇シンジ                     / 初号機  Sync rate: 41.30%
綾波レイ                     / 零号機  Sync rate: 57.20%
惣流・アスカ・ラングレー     / 弐号機  Sync rate: 98.00%
渚カヲル                     / 第4使徒  Sync rate: 100.00%
真希波・マリ・イラストリアス / 仮設5号機  Sync rate: 77.80%

Pilot: 碇シンジ                     Unit: 初号機  Sync rate: 41.30%

-v3.33

Summary

The printf command in shell scripts gives you complete control over output through a format string. Unlike echo, it does not append a trailing newline automatically — you include \n in the format string to add one explicitly. The most commonly used format specifiers are %s (string), %d (decimal integer), %f (floating-point), %x/%X (hexadecimal), and %o (octal). Specifying a field width applies right-alignment by default; the - flag switches to left-alignment, and the 0 flag enables zero-padding — all useful for producing tabular output. The %.2f syntax fixes the number of decimal places. Because printf is POSIX-compliant, it works safely in #!/bin/sh scripts and is especially valuable when you want to avoid the implementation-dependent behavior of echo -e and echo -n. Related commands include read (reading standard input) and here documents (multi-line output).

If you find any errors or copyright issues, please .