Möchten Sie die Differenzen zwischen zwei Textdatei-Versionen herausfinden? Hier kommt der Befehl `diff` ins Spiel. In diesem Tutorial zeigen wir Ihnen, wie Sie `diff` unter Linux und macOS auf unkomplizierte Art einsetzen können.
Eine detaillierte Betrachtung von `diff`
Der `diff`-Befehl nimmt zwei Dateien und erstellt eine Übersicht der Unterschiede zwischen ihnen. Genauer gesagt, er listet die Änderungen auf, die an der ersten Datei vorgenommen werden müssten, damit sie exakt mit der zweiten Datei übereinstimmt. Dieses Verständnis ist hilfreich, um die Ausgabe von `diff` zu interpretieren. Ursprünglich wurde `diff` dafür entwickelt, Abweichungen in Quellcodedateien zu identifizieren und eine für andere Programme, wie beispielsweise den `patch`-Befehl, lesbare Ausgabe zu generieren. Im folgenden Verlauf dieses Artikels werden wir die nützlichsten und anwenderfreundlichsten Anwendungsmöglichkeiten von `diff` beleuchten.
Beginnen wir gleich mit der Analyse von zwei Dateien. Die Reihenfolge, in der die Dateien in der Befehlszeile angegeben werden, legt fest, welche `diff` als „erste“ und welche als „zweite“ Datei behandelt. Im folgenden Beispiel ist `alpha1` die erste und `alpha2` die zweite Datei. Beide beinhalten das NATO-Buchstabieralphabet, jedoch wurde `alpha2` verändert, wodurch sie sich von `alpha1` unterscheidet.
Um die Dateien zu vergleichen, geben Sie `diff`, gefolgt von einem Leerzeichen, dem Namen der ersten Datei, einem weiteren Leerzeichen und dem Namen der zweiten Datei ein. Bestätigen Sie mit der Eingabetaste.
diff alpha1 alpha2
Wie interpretieren wir diese Ausgabe? Es ist einfacher, als es zunächst scheint, sobald man die grundlegenden Strukturen versteht. Jede festgestellte Differenz wird sequenziell in einer einzelnen Spalte aufgeführt und mit einer Markierung versehen. Diese Markierung enthält auf beiden Seiten eines Buchstabens Zahlen, beispielsweise `4c4`. Die erste Zahl gibt die Zeilennummer in `alpha1` und die zweite die Zeilennummer in `alpha2` an. Der Buchstabe in der Mitte kann folgendes bedeuten:
`c`: Die Zeile in der ersten Datei muss modifiziert werden, damit sie mit der entsprechenden Zeile in der zweiten Datei übereinstimmt.
`d`: Die Zeile muss in der ersten Datei entfernt werden, um Übereinstimmung mit der zweiten Datei zu erreichen.
`a`: Der ersten Datei muss zusätzlicher Inhalt hinzugefügt werden, damit sie mit der zweiten Datei übereinstimmt.
Das `4c4` in unserem Beispiel besagt, dass Zeile vier von `alpha1` geändert werden muss, um mit Zeile vier von `alpha2` identisch zu sein. Dies ist die erste erkannte Differenz zwischen den beiden Dateien.
Zeilen, die mit einem `<` beginnen, beziehen sich auf die erste Datei, `alpha1`. Die Zeile `Delta` zeigt den Inhalt der vierten Zeile in `alpha1` an.
Zeilen, die mit `>` anfangen, beziehen sich auf die zweite Datei, `alpha2`. Die Zeile `Dave` zeigt den Inhalt der vierten Zeile in `alpha2` an. Zusammenfassend lässt sich sagen, dass wir das Wort `Delta` in Zeile vier von `alpha1` durch `Dave` ersetzen müssen, um die Zeile in beiden Dateien identisch zu machen.
Die nächste Modifikation wird durch `12c12` dargestellt. Analog bedeutet dies, dass Zeile 12 in `alpha1` das Wort `Lima` enthält, während Zeile 12 in `alpha2` das Wort `Linux` enthält.
Die dritte Veränderung betrifft eine Zeile, die in `alpha2` nicht vorhanden ist. Die Markierung `21d20` ist so zu verstehen, dass die Zeile 21 aus der ersten Datei gelöscht werden muss, um die Dateien ab Zeile 20 zu synchronisieren. Die Zeile `Zulu` zeigt den Inhalt der 21. Zeile in der ersten Datei an.
Die vierte Abweichung ist mit `26a26,28` gekennzeichnet. Hierbei handelt es sich um drei zusätzliche Zeilen, die zu `alpha2` hinzugefügt wurden. Beachten Sie die Angabe `26,28` in der Markierung. Zwei durch ein Komma getrennte Zeilennummern stellen einen Bereich von Zeilennummern dar. In diesem Fall umfasst der Bereich die Zeilen 26 bis 28. Die Markierung bedeutet, dass „in Zeile 26 der ersten Datei die Zeilen 26 bis 28 aus der zweiten Datei hinzugefügt werden müssen“. Die drei Zeilen, die `alpha2` hinzugefügt wurden, enthalten die Worte `Quirk`, `Strange` und `Charm`.
Prägnante Einzeiler
Wenn Sie lediglich überprüfen möchten, ob zwei Dateien identisch sind, verwenden Sie die Option `-s` (identische Dateien melden).
diff -s alpha1 alpha3
Um eine genauso knappe Bestätigung zu erhalten, dass zwei Dateien unterschiedlich sind, nutzen Sie die Option `-q` (kurz).
diff -q alpha1 alpha2
Wichtig ist, dass bei zwei identischen Dateien die Option `-q` (kurz) keinerlei Ausgabe erzeugt.
Eine alternative Darstellungsweise
Die Option `-y` (nebeneinander) bietet eine andere Struktur, um die Unterschiede zwischen den Dateien zu veranschaulichen. Oftmals ist es ratsam, die Option `-W` (Breite) zusammen mit der nebeneinander Darstellung zu nutzen, um die Anzahl der angezeigten Spalten zu begrenzen. Dies vermeidet unübersichtliche Zeilenumbrüche und verbessert die Lesbarkeit. Im folgenden Beispiel haben wir `diff` angewiesen, eine nebeneinander Darstellung zu erstellen und die Ausgabe auf 70 Spalten zu beschränken.
diff -y -W 70 alpha1 alpha2
Die erste in der Befehlszeile genannte Datei, `alpha1`, wird links, die zweite, `alpha2`, rechts angezeigt. Die Zeilen der jeweiligen Dateien werden nebeneinander dargestellt. Neben den Zeilen in `alpha2`, die verändert, gelöscht oder hinzugefügt wurden, befinden sich Hinweiszeichen.
`|`: Eine Zeile, die in der zweiten Datei geändert wurde.
`<`: Eine Zeile, die aus der zweiten Datei gelöscht wurde.
`>`: Eine Zeile, die der zweiten Datei hinzugefügt wurde und nicht in der ersten Datei vorhanden ist.
Wenn Sie eine komprimiertere Übersicht der Dateidifferenzen bevorzugen, verwenden Sie die Option `–suppress-common-lines`. Diese zwingt `diff`, nur die modifizierten, hinzugefügten oder gelöschten Zeilen auszugeben.
diff -y -W 70 --suppress-common-lines alpha1 alpha2
Einen Farbtupfer hinzufügen
Ein weiteres Tool, `colordiff`, versieht die `diff`-Ausgabe mit farblichen Markierungen. Dadurch wird es deutlich einfacher, Abweichungen in den Zeilen zu identifizieren.
Nutzen Sie `apt-get` zur Installation dieses Pakets auf Ihrem System, wenn Sie Ubuntu oder eine andere Debian-basierte Distribution verwenden. Bei anderen Linux-Distributionen verwenden Sie das entsprechende Paketverwaltungstool Ihrer Distribution.
sudo apt-get install colordiff
Verwenden Sie `colordiff` analog zu `diff`.
Eigentlich fungiert `colordiff` als Wrapper für `diff` und `diff` erledigt die eigentliche Arbeit im Hintergrund. Daher sind alle `diff`-Optionen auch mit `colordiff` kompatibel.
Kontext bereitstellen
Um einen Mittelweg zwischen der Anzeige aller Zeilen der Dateien und der Anzeige lediglich der veränderten Zeilen zu finden, kann `diff` so konfiguriert werden, dass es Kontext mitliefert. Hierfür gibt es zwei Ansätze. Beide verfolgen das gleiche Ziel, nämlich die Anzeige einiger Zeilen vor und nach jeder veränderten Zeile. So kann die Umgebung des Unterschieds innerhalb der Datei besser erkannt werden.
Der erste Ansatz ist die Verwendung der Option `-c` (kontextbasiert).
colordiff -c alpha1 alpha2
Die `diff`-Ausgabe beginnt mit einem Header. Der Header enthält die Namen der beiden Dateien und deren Änderungszeiten. Es werden Sternchen `*` vor dem Namen der ersten Datei und Bindestriche `-` vor dem Namen der zweiten Datei gesetzt. Sternchen und Bindestriche dienen dazu anzugeben, zu welcher Datei die Zeilen in der Ausgabe gehören.
Eine Zeile aus Sternchen mit `1,7` in der Mitte deutet an, dass es sich um Zeilen aus `alpha1` handelt. Genauer gesagt, betrachten wir die Zeilen eins bis sieben. Das Wort `Delta` ist als verändert markiert. Es wird durch ein Ausrufezeichen `!` daneben und die rote Farbe hervorgehoben. Vor und nach dieser Zeile werden drei Zeilen mit unverändertem Text angezeigt, um den Kontext dieser Zeile innerhalb der Datei zu verdeutlichen.
Die Zeile mit Bindestrichen und der Angabe `1,7` zeigt an, dass wir uns jetzt die Zeilen aus `alpha2` ansehen. Wiederum betrachten wir die Zeilen eins bis sieben, wobei das Wort `Dave` in Zeile vier als unterschiedlich markiert ist.
colordiff -C 2 alpha1 alpha2
Standardmäßig werden drei Zeilen Kontext über und unter jeder Änderung angezeigt. Sie können die Anzahl der Kontextzeilen, die `diff` bereitstellen soll, auch festlegen. Nutzen Sie hierfür die Option `-C` (kontextbasiert) mit einem großen `C` und geben Sie die gewünschte Zeilenanzahl an:
colordiff -u alpha1 alpha2
Die zweite Option zur Bereitstellung von Kontext in `diff` ist die Option `-u` (vereinheitlichter Kontext).
Wie zuvor beginnt die Ausgabe mit einem Header, der die Dateinamen und deren Änderungszeiten auflistet. Dem Dateinamen von `alpha1` wird ein Bindestrich `-` vorangestellt, dem von `alpha2` ein Pluszeichen `+`. Dies deutet an, dass Bindestriche verwendet werden, um auf `alpha1` zu verweisen und Pluszeichen, um auf `alpha2` zu verweisen. In der gesamten Auflistung finden sich Zeilen, die mit einem At-Zeichen `@` beginnen. Diese Zeilen markieren den Beginn jeder Differenz. Sie geben auch an, welche Zeilen aus jeder Datei angezeigt werden.
Uns werden die drei Zeilen vor und nach der als unterschiedlich markierten Zeile angezeigt, um den Kontext der veränderten Zeile erkennen zu können. In der vereinheitlichten Ansicht werden die Zeilen mit dem Unterschied übereinander dargestellt. Die Zeile aus `alpha1` hat einen Bindestrich vorangestellt und die Zeile aus `alpha2` ein Pluszeichen. Diese Anzeige erreicht in acht Zeilen dasselbe, wofür die oben gezeigte kontextbasierte Anzeige fünfzehn Zeilen benötigte.
colordiff -U 2 alpha1 alpha2
Wie zu erwarten ist, können wir `diff` anweisen, die genaue Anzahl der Zeilen des vereinheitlichten Kontexts anzugeben, die angezeigt werden sollen. Verwenden Sie dazu die Option `-U` (Unified Context) mit einem großen „U“ und geben Sie die gewünschte Zeilenanzahl an:
Leerzeichen und Groß-/Kleinschreibung ignorieren
colordiff -y -W 70 test4 test5
Betrachten wir zwei weitere Dateien, `test4` und `test5`. Diese enthalten Namen von sechs Superhelden.
Die Ergebnisse zeigen, dass `diff` bei den Zeilen `Black Widow`, `Spider-Man` und `Thor` keine Unterschiede feststellt. Es zeigt aber Abweichungen bei den Zeilen `Captain America`, `Ironman` und `The Hulk` an.
Was ist also anders? In `test5` wird `Hulk` mit einem kleinen `h` geschrieben und `Captain America` hat ein zusätzliches Leerzeichen zwischen `Captain` und `America`. Das ist soweit ersichtlich, aber was ist mit der Zeile `Ironman` falsch? Es gibt keine sichtbaren Unterschiede. Hier gilt eine einfache Regel: Wenn Sie es nicht sehen können, ist die Antwort wahrscheinlich „Leerzeichen“. Wahrscheinlich gibt es ein oder zwei zusätzliche Leerzeichen oder einen Tab am Ende dieser Zeile.
Wenn Ihnen diese Unterschiede nicht wichtig sind, können Sie `diff` anweisen, bestimmte Arten von Zeilenunterschieden zu ignorieren, darunter:
`-i`: Unterschiede in der Groß- und Kleinschreibung ignorieren.
`-Z`: Nachfolgende Leerzeichen ignorieren.
`-b`: Veränderungen in der Anzahl der Leerzeichen ignorieren.
`-w`: Alle Änderungen an Leerzeichen ignorieren.
colordiff -i -y -W 70 test4 test5
Lassen Sie uns `diff` bitten, diese beiden Dateien erneut zu prüfen, diesmal jedoch alle Unterschiede in der Groß- und Kleinschreibung zu ignorieren.
colordiff -i -Z -y -W 70 test4 test5
Die Zeilen mit `The Hulk` und `The Hulk` werden nun als identisch betrachtet und es wird kein Unterschied wegen des kleinen `h` angezeigt. Bitten wir `diff` nun auch, nachfolgende Leerzeichen zu ignorieren.
colordiff -i -w -y -W 70 test4 test5
Wie erwartet, war das nachfolgende Leerzeichen der Unterschied in der Zeile von Ironman, da `diff` für diese Zeile keinen Unterschied mehr anzeigt. Es verbleibt `Captain America`. Bitten wir `diff`, nun die Groß-/Kleinschreibung zu ignorieren und alle Probleme mit Leerzeichen zu ignorieren.
Indem wir `diff` anweisen, die Unterschiede zu ignorieren, die für uns nicht relevant sind, gibt `diff` uns die Information, dass die Dateien für unsere Zwecke übereinstimmen. Der `diff`-Befehl bietet eine Vielzahl weiterer Optionen, von denen sich die meisten auf die Erstellung einer maschinenlesbaren Ausgabe beziehen. Diese können unter Linux in der Man-Page eingesehen werden.
Die Optionen, die wir in den obigen Beispielen genutzt haben, ermöglichen Ihnen, sämtliche Unterschiede zwischen den Versionen Ihrer Textdateien mithilfe der Kommandozeile und Ihres eigenen Auges aufzuspüren.