Während echo für schnelle Ausgaben reicht, ist printf das Werkzeug für ernsthafte Shell-Skripte: Es nimmt einen Format-String und beliebig viele Argumente entgegen, fügt sie nach klar definierten Regeln zusammen und verhält sich auf jeder POSIX-Shell identisch. Wer aus C kommt, kennt das Prinzip — %s, %d, %f und Konsorten funktionieren in Bash ganz genauso.

Was printf macht

printf schreibt Text auf die Standardausgabe — aber im Gegensatz zu echo nach einem Format-String, der bestimmt, wie die übergebenen Argumente dargestellt werden. Das Modell ist direkt aus der C-Standardbibliothek entliehen und damit der Shell-Programmierung vertraut, sobald man einmal eine Programmiersprache mit printf gesehen hat.

Bash Grundform
printf '%s ist %d Jahre alt\n' "Max" 42
Output
Max ist 42 Jahre alt

Drei wichtige Eigenschaften unterscheiden printf grundlegend von echo:

  • Kein automatisches Newline. Wer eine neue Zeile will, schreibt \n selbst in den Format-String. Das wirkt zunächst unbequem, gibt aber volle Kontrolle.
  • Escape-Sequenzen werden immer interpretiert — kein -e-Flag nötig. \n, \t, \\ funktionieren direkt.
  • Portabel. Die POSIX-Spezifikation für printf ist eng definiert; das Verhalten ist auf Bash, Zsh, Dash, Ksh und allen seriösen Shells identisch.

printf vs. echo

Beide Werkzeuge geben Text aus — aber für ernsthafte Skripte ist die Wahl klar.

Aspektechoprintf
Newline am Endeautomatisch (außer mit -n)nur wenn explizit \n
Escape-Sequenzennur mit -e (Bash), in Zsh standardmässigimmer interpretiert
Portabilitätuneinheitlich (Bash/Zsh/Dash/BSD verhalten sich unterschiedlich)POSIX-spezifiziert, überall gleich
Format-Specifierkeine%s, %d, %f, %x und mehr
Width und Precisionnicht möglich%-20s, %.3f, %5d
Argumente mit -werden teilweise als Optionen interpretiertArgumente nach dem Format sind sicher
In Variable schreibennur über Subshell $(...)direkt mit printf -v (Bash)

Format-Specifier

Ein Format-Specifier beginnt mit % und beschreibt, wie ein Argument dargestellt wird. Zwischen % und dem Typbuchstaben können optional Flags, Width und Precision stehen.

SpecifierBedeutungBeispiel-EingabeBeispiel-Ausgabe
%sStringHalloHallo
%d / %iInteger (dezimal)4242
%fGleitkommazahl, Standard 6 Nachkommastellen3.143.140000
%ewissenschaftliche Notation12345.61.234560e+04
%gkompakteste sinnvolle Darstellung0.0001230.000123
%x / %XHexadezimal (klein/groß)255ff / FF
%oOktal810
%ceinzelnes ZeichenAA
%bString mit Escape-Interpretation im ArgumentZeile\nNeuzwei Zeilen
%qshell-quoted (sicheres Re-Parsing)Hello WorldHello\ World
%%literales Prozentzeichen%
Bash Specifier in Aktion
printf '%s = %d (hex: %x, oct: %o)\n' "Wert" 255 255 255
printf 'Pi ungefähr %f, kompakt %g\n' 3.14159 3.14159
printf 'Rabatt %d%% auf alles\n' 20
Output
Wert = 255 (hex: ff, oct: 377)
Pi ungefähr 3.141590, kompakt 3.14159
Rabatt 20% auf alles

Width und Precision

Zwischen % und dem Typbuchstaben kann eine Mindestbreite und eine Genauigkeit stehen. Damit lassen sich Tabellen exakt ausrichten.

FormWirkung
%5dInteger, mindestens 5 Zeichen breit, rechts-bündig (mit Leerzeichen aufgefüllt)
%-10sString, mindestens 10 Zeichen breit, links-bündig (Minus-Flag)
%05dInteger, mit führenden Nullen auf 5 Stellen aufgefüllt
%.3fFloat mit genau 3 Nachkommastellen
%10.3fFloat, gesamt 10 Zeichen breit, davon 3 nach dem Komma
%-20s%5dKombination: 20 Zeichen links-bündiger String, danach 5 Zeichen rechts-bündige Zahl
%*dWidth wird als Argument übergeben (dynamisch)
Bash Tabelle mit fester Spaltenbreite
printf '%-15s %5s %8s\n' "Name" "Alter" "Saldo"
printf '%-15s %5d %8.2f\n' "Anna" 32 1234.50
printf '%-15s %5d %8.2f\n' "Maximilian" 45 99.95
printf '%-15s %5d %8.2f\n' "Bo" 7 0.10
Output
Name            Alter    Saldo
Anna               32  1234.50
Maximilian         45    99.95
Bo                  7     0.10

Mit dem dynamischen Width-Parameter * lässt sich die Breite zur Laufzeit bestimmen — das Argument unmittelbar vor dem Wert wird als Breite gelesen.

Bash Dynamische Width
breite=12
printf '%*s|\n' "$breite" "rechts"
Output
      rechts|

Escape-Sequenzen

Im Format-String werden Backslash-Escapes immer interpretiert — anders als bei echo ist kein Flag nötig.

SequenzBedeutung
\nZeilenumbruch (Newline)
\thorizontaler Tabulator
\rCarriage Return
\\literaler Backslash
\"literales doppeltes Anführungszeichen
\aBell (akustisches Signal)
\xHHByte mit hexadezimalem Wert HH
\NNNByte mit oktalem Wert NNN
\uHHHHUnicode-Codepoint (Bash-builtin, 4 Hex-Stellen)
\UHHHHHHHHUnicode-Codepoint (Bash-builtin, 8 Hex-Stellen)
Bash Escape-Sequenzen mischen
printf 'A=\x41 Pi=π Euro=€\n'
printf 'Pfad:\t/etc/hosts\nMode:\t0644\n'
Output
A=A Pi=π Euro=€
Pfad:   /etc/hosts
Mode:   0644

Reuse von Format-String

Eines der nützlichsten Features: Wenn mehr Argumente übergeben werden als Format-Specifier vorhanden sind, wird der Format-String wiederholt, bis alle Argumente verbraucht sind.

Bash Reuse-Mechanismus
printf '%s\n' a b c d
Output
a
b
c
d

Statt eine Schleife zu schreiben, übergibst du einfach alle Werte. Das funktioniert genauso mit mehreren Specifiern — printf arbeitet dann den Format-String pro Specifier-Gruppe ab.

Bash Reuse mit mehreren Specifiern
printf '%-10s %d\n' "Anna" 32 "Bert" 45 "Carla" 28
Output
Anna       32
Bert       45
Carla      28

Ideal für Listen aus Arrays. printf '%s\n' "${arr[@]}" druckt jeden Eintrag in eine eigene Zeile — ohne Schleife, ohne for.

Praxis-Patterns

Tabelle formatieren

Mit %-20s als links-bündigem String und %5d als rechts-bündigem Integer richtest du Spalten exakt an einer Pixelkante aus — unabhängig davon, wie lang die einzelnen Werte sind. Das ist der zuverlässigste Weg, eine lesbare Tabelle ohne externe Tools wie column zu bauen.

Bash Tabellarische Ausgabe
printf '%-20s %5s\n' "Service" "Port"
printf '%-20s %5d\n' "ssh" 22
printf '%-20s %5d\n' "http" 80
printf '%-20s %5d\n' "https" 443
Output
Service               Port
ssh                     22
http                    80
https                  443

CSV erzeugen

Anders als echo mit interpolierten Variablen umgeht printf Probleme mit Sonderzeichen oder Werten, die mit - beginnen. Achtung: Enthält ein Wert selbst ein Komma oder Anführungszeichen, brauchst du echtes CSV-Quoting — printf kümmert sich nicht um RFC-4180-Escaping.

Bash CSV-Zeile schreiben
printf '%s,%s,%d\n' "Anna" "anna@example.com" 32
Output
Anna,anna@example.com,32

In Variable schreiben mit -v

In Bash schreibt printf -v VARNAME ... direkt in eine Variable — ohne Subshell, ohne Performance-Overhead von $(...).

Bash printf -v
printf -v greeting 'Hallo, %s!' "Welt"
echo "$greeting"
Output
Hallo, Welt!

Log-Zeile mit Timestamp

Die Kombination aus date-Substitution und %-5s für das Level erzeugt strukturiertes, gleichmäßig ausgerichtetes Logging — gut lesbar im Terminal und problemlos mit awk oder grep auswertbar. Das %-5s sorgt dafür, dass INFO, WARN und ERROR alle gleich breit ausgegeben werden.

Bash Strukturiertes Logging
printf '[%s] %-5s %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "INFO" "Backup gestartet"
Output
[2026-05-05 14:32:01] INFO  Backup gestartet

JSON manuell zusammenstellen

Für kleine, kontrollierte Fälle (für komplexes JSON nimm jq):

Bash JSON-Objekt
name="Anna"
age=32
printf '{"name":"%s","age":%d}\n' "$name" "$age"
Output
{"name":"Anna","age":32}

Besonderheiten

Builtin oder Binary — type -a printf zeigt es

In Bash ist printf ein eingebauter Befehl; daneben existiert das eigenständige Programm /usr/bin/printf aus den GNU Coreutils. Mit type -a printf listest du beide auf. Im Alltag spielt das selten eine Rolle, aber subtile Unterschiede gibt es: Das Builtin kennt printf -v (in Variable schreiben), das Binary nicht. Umgekehrt akzeptiert das Binary die Option --, das Builtin nicht. Mit command printf ... oder dem absoluten Pfad erzwingst du das externe Programm.

%b interpretiert Escapes im Argument — gefährlich mit User-Input

Während %s ein Argument unverändert ausgibt, interpretiert %b Backslash-Sequenzen innerhalb des Arguments. printf '%b\n' 'Zeile\nNeu' erzeugt zwei Zeilen. Das ist praktisch, wenn du Escapes in Variablen aktiv interpretieren willst — aber gefährlich, sobald die Werte aus unkontrollierter Quelle stammen. Ein Angreifer kann mit \e[2J den Bildschirm löschen oder mit \xHH beliebige Bytes einschleusen. Für fremden Input gilt: immer %s, nie %b.

Locale beeinflusst Float-Output — Komma vs. Punkt

printf '%f\n' 3.14 gibt unter LC_NUMERIC=de_DE.UTF-8 tatsächlich 3,140000 aus — mit Komma als Dezimaltrenner. Das bricht Skripte, die die Ausgabe weiterverarbeiten oder in Dateien schreiben, die später woanders gelesen werden. Für reproduzierbare numerische Ausgabe immer LC_NUMERIC=C printf ... oder export LC_NUMERIC=C am Skriptanfang verwenden. Das gilt auch für awk, bc und alle anderen Werkzeuge, die Zahlen formatieren.

%q für sicheres Quoting in generierten Skripten

printf '%q\n' "Hallo Welt mit 'Sonderzeichen'" gibt einen String aus, der von der Shell wieder eingelesen werden kann, ohne dass Sonderzeichen Schaden anrichten. Ideal, wenn du Skripte oder Befehle dynamisch zusammenbaust und an eval, bash -c oder eine Datei weitergibst. %q ist das Bash-Pendant zu shlex.quote() aus Python — sicheres Quoting für die Shell.

Reuse-Mechanismus ersetzt for-Schleifen

Wenn mehr Argumente als Specifier vorhanden sind, wird der Format-String wiederholt. printf '%s\n' "${array[@]}" druckt jedes Element des Arrays in eine eigene Zeile — ohne for, ohne Indexierung. Das ist nicht nur kürzer, sondern auch deutlich schneller als eine Schleife mit einzelnen echo-Aufrufen, weil nur ein einziger printf-Aufruf nötig ist. Auch mit mehreren Specifiern: printf '%s=%s\n' key1 val1 key2 val2 key3 val3 erzeugt drei Zeilen.

printf akzeptiert kein -- als Argumentterminator

Das Builtin printf kennt kein -- zum Beenden der Optionen. Argumente, die direkt nach dem Format-String stehen und mit - beginnen, können in Sonderfällen als Option missinterpretiert werden — vor allem, wenn der Format-String selbst leer oder unsauber ist. Sicherer Stil: Format-String immer in einfache Anführungszeichen einschließen und Werte explizit als Argumente übergeben. printf '%s\n' "$value" ist auch dann sicher, wenn $value mit -n oder -e beginnt — das ist genau der Vorteil gegenüber echo.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Textverarbeitung

Zur Übersicht