diff vergleicht zwei Files zeilenweise und meldet, welche Zeilen sich unterscheiden, hinzugekommen oder entfernt sind. Die Ausgabe lässt sich in mehreren Formaten erzeugen — vom kompakten Normal-Format bis zum Unified-Format, das als De-facto-Standard für Patches gilt und sich direkt mit patch einspielen lässt. diff -r arbeitet rekursiv über ganze Verzeichnisbäume, was es zum unverzichtbaren Werkzeug für Code-Reviews, Backups und Konfigurationsabgleiche macht.

Was diff macht

diff liest zwei Eingaben — zwei Files, ein File und stdin (-), oder zwei Verzeichnisse — und berechnet die minimalen Änderungen, mit denen sich die erste Eingabe in die zweite überführen lässt. Die Ausgabe ist deterministisch, maschinenlesbar und in mehreren Formaten verfügbar.

Typische Einsatzgebiete:

  • Code-Reviews ohne Versionskontrolle — schnell prüfen, was sich zwischen zwei Files geändert hat
  • Patch-Erzeugungdiff -u alt neu > fix.patch produziert einen Patch, den patch einspielen kann
  • Konfigurationsabgleich — z. B. /etc/nginx/nginx.conf vor und nach einem Update vergleichen
  • Verzeichnisse synchronisierendiff -r dir1 dir2 --brief zeigt Unterschiede auf Datei-Ebene
  • Skript-Logik — Exit-Code 0/1/2 lässt sich in if-Bedingungen direkt nutzen

Default-Output (Normal-Format)

Ohne weitere Optionen liefert diff das Normal-Format. Zeilen aus dem ersten File werden mit < markiert, Zeilen aus dem zweiten File mit >. Davor steht ein Hunk-Header, der die betroffenen Zeilennummern und die Art der Änderung beschreibt: c für change, a für append, d für delete.

Bash Normal-Format
diff alt.txt neu.txt
Output
1c1
< Hallo Welt
---
> Hallo Linux
3a4
> Neue Zeile am Ende

Lesart: In Zeile 1 wurde der Inhalt geändert (1c1), nach Zeile 3 wurde an Position 4 etwas angehängt (3a4). Ein Block wie 4d3 würde bedeuten, dass Zeile 4 aus dem ersten File gelöscht wurde und im zweiten File hinter Position 3 fehlt.

Wichtige Optionen

OptionWirkung
-u, --unifiedUnified-Format mit Kontext — Standard für Patches
-c, --contextKlassisches Context-Format mit drei Zeilen Kontext
-y, --side-by-sideZweispaltige Darstellung nebeneinander
-r, --recursiveRekursiver Vergleich zweier Verzeichnisse
-q, --briefNur melden, dass sich Files unterscheiden, nicht wie
-i, --ignore-caseGroß-/Kleinschreibung ignorieren
-w, --ignore-all-spaceSämtliche Whitespace-Unterschiede ignorieren
-B, --ignore-blank-linesReine Leerzeilen-Unterschiede ausblenden
--color=autoFarbige Ausgabe im Terminal
-N, --new-fileFehlende Files wie leere Files behandeln (wichtig für Patches)
-x PATTERNFiles/Pfade mit Muster vom Vergleich ausschließen
-sAuch melden, wenn Files identisch sind

Unified-Format -u

Das Unified-Format ist der De-facto-Standard für Patches und das Format, das git diff, GitHub und patch lesen. Jeder Hunk beginnt mit einem Header der Form @@ -L,N +L,N @@: links die Zeilen aus dem alten File (Start L, Anzahl N), rechts die aus dem neuen.

Bash Unified-Format
diff -u alt.txt neu.txt
Output
--- alt.txt    2026-05-04 10:00:00.000000000 +0200
+++ neu.txt    2026-05-04 10:05:00.000000000 +0200
@@ -1,3 +1,4 @@
-Hallo Welt
+Hallo Linux
 Zweite Zeile
 Dritte Zeile
+Neue Zeile am Ende

Zeilen mit - stammen aus dem alten File, Zeilen mit + aus dem neuen, Zeilen ohne Präfix sind Kontext (per Default drei Zeilen vor und nach jeder Änderung). Der gesamte Output lässt sich in eine Datei umlenken und mit patch < fix.patch wieder einspielen.

Verzeichnisse vergleichen

Mit -r arbeitet diff rekursiv durch zwei Verzeichnisbäume. Kombiniert mit --brief bekommst du eine reine Übersicht, welche Files sich unterscheiden, ohne jeden Hunk zu sehen.

Bash Verzeichnisse vergleichen
diff -r --brief --exclude='.git' projektA projektB
Output
Files projektA/README.md and projektB/README.md differ
Only in projektB: CHANGELOG.md
Files projektA/src/main.go and projektB/src/main.go differ

-x PATTERN (oder das ausführliche --exclude=PATTERN) blendet Pfade aus — typisch sind .git, node_modules, dist oder *.log. Mehrere -x-Flags sind erlaubt. Mit -N werden Files, die nur in einem Baum existieren, behandelt, als wären sie auf der anderen Seite leer — das ergibt sauberere Patches über ganze Projekte.

Praxis-Patterns

Patch erzeugen und einspielen. Der klassische Workflow für Patches ohne Git:

Bash Patch-Workflow
diff -u alt.conf neu.conf > fix.patch
patch alt.conf < fix.patch

Schnell prüfen, ob zwei Files identisch sind. Mit -q wird nur eine kurze Meldung erzeugt, der Exit-Code reicht für Skripte:

Bash Identitäts-Check
diff -q a.txt b.txt && echo "identisch" || echo "unterschiedlich"

Side-by-Side ohne Rauschen. -y --suppress-common-lines zeigt nur die Zeilen, die sich tatsächlich unterscheiden — viel übersichtlicher bei langen Files:

Bash Side-by-Side
diff -y --suppress-common-lines alt.txt neu.txt

Farbiger Diff. Mit --color=auto wird die Ausgabe im Terminal eingefärbt. Für noch hübschere Ausgabe gibt es colordiff als Wrapper:

Bash Farbig
diff --color=auto -u alt.txt neu.txt
colordiff -u alt.txt neu.txt

diff vs. git diff vs. cmp

WerkzeugGranularitätTypischer Use-CaseFormat
diffZeilenweise, TextBeliebige zwei Files/Verzeichnisse vergleichenNormal, Unified, Context, Side-by-Side
git diffZeilenweise, TextÄnderungen im Git-Repo (Working Tree, Index, Commits)Unified mit Git-Erweiterungen
cmpByte für Byte, binärBinär-Files, Backups, Image-VergleichErste Abweichung oder alle Bytes

Für reine Text-Files reicht diff fast immer. Sobald du ein Git-Repo verwaltest, ist git diff ergonomischer (Index, Stash, Branches). Für Binär-Files ist cmp das richtige Werkzeug — diff quittiert sie mit Binary files ... differ und liefert keine Details.

Besonderheiten

Exit-Code als Skript-Signal: 0, 1, 2

diff setzt drei klar definierte Exit-Codes: 0 wenn die Eingaben gleich sind, 1 wenn sie sich unterscheiden, 2 bei einem echten Fehler (Datei nicht lesbar, Pfad existiert nicht). Diese Trennung ist gold wert für Skripte: if diff -q a b; then ... reagiert nur auf Identität, [ $? -eq 2 ] lässt sich für Fehlerbehandlung nutzen. Viele Tools vermischen Exit-Code 1 und 2 — diff nicht.

Unified-Format hat per Default drei Kontextzeilen

Mit -u bekommst du -u3 — drei Zeilen Kontext vor und nach jedem Hunk. Für engere oder breitere Patches lässt sich der Wert anpassen, etwa diff -u5 oder diff -U0 (überhaupt kein Kontext). Bei sehr kleinen Änderungen in großen Files kann -U0 die Patch-Datei drastisch verkürzen — überlappende Hunks werden dann allerdings nicht zusammengefasst und Patches sind sensibler gegenüber Verschiebungen.

Speicherhungrig bei sehr großen Files

diff lädt seine Eingaben in den Speicher und berechnet einen optimalen Diff über einen Algorithmus auf Basis der längsten gemeinsamen Teilfolge. Bei mehreren Hundert MB pro File kann das den RAM sprengen. Für Logfiles oder Datenbank-Dumps lohnt es sich, vorher mit head/tail/split einzugrenzen oder direkt auf zeilensortierte Vergleiche mit comm zu wechseln.

Binär-Files werden abgelehnt

Sobald diff ein NUL-Byte in einer Eingabe findet, schaltet es um auf Binary files A and B differ und gibt keinen Inhalt aus. Mit --text lässt sich der Vergleich erzwingen, das Ergebnis ist aber selten lesbar. Für Binär-Files ist cmp (Byte-Vergleich) oder die Kombination xxd a | diff - <(xxd b) der bessere Weg — letzterer liefert einen Hex-Dump-Diff, in dem du die Abweichungen tatsächlich sehen kannst.

Whitespace-Optionen unterscheiden sich von git diff

diff -w ignoriert alle Whitespace-Unterschiede, -b nur Mengenunterschiede, -B nur Leerzeilen, --ignore-trailing-space nur Trailing Spaces. git diff kennt mit -w, -b, --ignore-blank-lines ähnliche, aber nicht 1:1 deckungsgleiche Schalter. Wenn du Diffs zwischen Tools austauschst, lohnt es sich, die exakten Whitespace-Regeln zu prüfen — sonst wundert man sich, warum derselbe Patch in einem Werkzeug sauber ist und im anderen Konflikte erzeugt.

Reihenfolgewechsel sehen oft chaotisch aus

Wenn du in einem File nur zwei Blöcke vertauschst, produziert diff häufig einen riesigen Hunk: Es markiert den ersten Block als gelöscht und denselben Block weiter unten als hinzugefügt — plus die Zwischenzeilen als Kontext. Das ist algorithmisch korrekt, optisch aber irreführend. Tools wie git diff --color-moved oder dedizierte Move-Detector erkennen Verschiebungen explizit; diff kann das nicht.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Textverarbeitung

Zur Übersicht