Wie man einen zeilenweisen Vergleich von Dateien unter Linux mit dem Befehl diff durchführt – Teil II

Im ersten Teil dieser Diff-Befehls-Tutorialserie haben wir die Grundlagen des Befehls diskutiert, einschließlich der Frage, wie er funktioniert und wie die Ausgabe, die er erzeugt, verstanden werden kann. Obwohl mit diesem Befehlszeilenprogramm definitiv eine gewisse Lernkurve verbunden ist, lohnt es sich zu lernen, besonders wenn Ihre tägliche Arbeit darin besteht, dateibezogene Aufgaben auf einem CLI-only Linux-Computer auszuführen.

Unter der Annahme, dass Sie die grundlegende Verwendung des Befehls diff bereits kennen, werden wir in diesem Tutorial die verschiedenen Befehlszeilenoptionen des Tools anhand einiger leicht verständlicher Beispiele diskutieren.

Aber bevor wir fortfahren, denken Sie daran, dass alle Beispiele in diesem Tutorial auf Ubuntu 14.04 mit Bash Version 4.3.11(1) und diff Version 3.3 getestet wurden.

 

Unterschiedliche Befehlsoptionen

1. Berichten Sie, wenn die Dateien identisch sind.

Wenn der Befehl diff feststellt, dass die zu vergleichenden Dateien identisch sind, erzeugt er standardmäßig keine Ausgabe.

$ diff file1 file2
$

Es gibt jedoch eine Befehlszeilenoption (-s), mit der Sie den Befehl zwingen können, dies in der Ausgabe zu melden:

$ diff -s file1 file2
Files file1 and file2 are identical

2. Kopierter Kontext und vereinheitlichter Kontext

Dies sind grundsätzlich zwei verschiedene Formate, in denen der Befehl diff seine Ausgabe erzeugen kann. Der kopierte Kontext wird über die Befehlszeilenoption -c aktiviert, während der Unified-Kontext über -u aktiviert wird. Nachfolgend ein Beispiel für das erstere:

$ diff -c file1 file2
*** file1 2016-12-29 09:36:47.175597647 +0530
--- file2 2016-12-29 09:19:55.799558326 +0530
***************
*** 1,3 ****
Hi
! Helllo
Bye
--- 1,3 ----
Hi
! Hello
Bye

Im Ausgabeformat Kopierter Kontext werden die unterschiedlichen Zeilen also durch ein Ausrufezeichen (!) gekennzeichnet.

Und hier ist das Beispiel für das Unified Context-Format:

$ diff -u file1 file2
--- file1 2016-12-29 09:36:47.175597647 +0530
+++ file2 2016-12-29 09:19:55.799558326 +0530
@@ -1,3 +1,3 @@
Hi
-Helllo
+Hello
Bye

In diesem Ausgabeformat- bezeichnen Symbole vor den Zeilen Versionen der unterschiedlichen Zeile: ‚-‚, wenn in der Datei1 eine Zeile fehlt, ‚+‘, wenn in der Datei2 eine Zeile2hinzugefügt wurde.1.

3. Ausgabe eines’ed‘-Skripts

Der Befehl diff ist auch in der Lage, Befehle zu erzeugen, mit denen der Editor’ed‘ die Originaldatei (file1 in unseren Beispielen hier) in die neue Datei (file2) konvertieren kann. Hier ist, wie du das machst:

Angenommen, file1 und file2 enthalten die folgende Änderung:

$ diff file1 file2
2c2
< Helllo
---
> Hello

Verwenden Sie nun die Befehlszeilenoption -e, um die Ausgabe zu erzeugen, die der Editor’ed‘ versteht, und leiten Sie diese Ausgabe in eine Datei um:

diff -e file1 file2 > out

Hier ist, was in diesem Fall herauskommt:

2c
Hello
.

Was Sie als nächstes tun müssen, ist, den Befehl ‚w‘ am Ende der Ausgabedatei hinzuzufügen.

2c
Hello
.
w

Führen Sie nun den folgenden Befehl aus:

ed - file1 < out

Und du wirst sehen, dass file1 und file2 jetzt identisch sind.

$ diff file1 file2
$

Weitere Informationen zu dieser Funktionalität finden Sie hier.

4. Produzieren Sie die Ausgabe in zwei Spalten

Normalerweise erzeugt der Befehl diff die Ausgabe wie folgt:

$ diff file1 file2
2c2
< Helllo
---
> Hello

Es gibt jedoch eine Befehlszeilenoption (-y), die diff anweist, die Ausgabe in zwei getrennten Spalten zu erzeugen. Hier ist ein Beispiel:

$ diff -y file1 file2
Hi                               Hi
Helllo                         | Hello
Bye                              Bye

Wie Sie sehen können, verwendet dieses Ausgabeformat ein ‚|‘, um Zeilen anzuzeigen, die sich unterscheiden.

5. Gemeinsame Linien ausblenden

Wenn Sie die im vorherigen Abschnitt (Punkt 4 oben) dargestellte Ausgabe betrachten, werden Sie feststellen, dass mit der Option -y command line, diff – in der Ausgabe – auch gemeinsame Linien erzeugt werden. Falls Sie diese identischen Zeilen unterdrücken müssen, können Sie die Option –suppress-common-lines verwenden.

himanshu@himanshu-desktop:~$ diff -y --suppress-common-lines file1 file2
Helllo                                   | Hello

6. Zeigt die C-Funktion an, in der sich jede Änderung befindet.

Für Fälle, in denen Sie diff verwenden, um zwei C-Sprachdateien zu vergleichen, gibt es eine Befehlszeilenoption (-p), die das Dienstprogramm anweist, genau anzuzeigen, in welcher C-Funktion sich jede Änderung befindet. Angenommen, dies sind die beiden C-Dateien:

file1.c:

#include<stdio.h>

void compare(float x, float y)
{
if(x == y) // incorrect way
{
printf(„\n EQUAL \n“);
}
}

int main(void)
{
compare(1.234, 1.56789);

return 0;
}

file2.c:

#include<stdio.h>

void compare(float x, float y)
{
if(x == y)
{
printf(„\n EQUAL \n“);
}
}

int main(void)
{
compare(1.234, 1.56789);

return 0;
}

Hier ist die Ausgabe, wenn beide Dateien normal verglichen werden:

$ diff file1.c file2.c 
5c5
< if(x == y) // incorrect way
---
> if(x == y)

Und hier ist die Ausgabe, wenn die Dateien mit der Option -p verglichen werden:

$ diff -p file1.c file2.c 
*** file1.c 2016-12-29 11:45:36.587010816 +0530
--- file2.c 2016-12-29 11:46:39.823013274 +0530
***************
*** 2,8 ****

void compare(float x, float y)
{
! if(x == y) // incorrect way
{
printf(„\n EQUAL \n“);
}
— 2,8 —-

void compare(float x, float y)
{
! if(x == y)
{
printf(„\n EQUAL \n“);
}

Wie Sie also sehen können, gibt Ihnen diff mit -p einen detaillierteren Einblick, wo sich die Änderung befindet, indem es die unterschiedlichen Zeilen mit einem Ausrufezeichen (!) anzeigt.

7. Rekursives Vergleichen von Unterverzeichnissen

Mit dem Befehl diff können Sie auch Unterverzeichnisse rekursiv vergleichen, aber das ist nicht das Standardverhalten. Was ich sagen will, ist, wenn Sie den folgenden Fall übernehmen:

$ diff diff-files/ second-diff-files/
diff diff-files/file1 second-diff-files/file1
1c1
< Hi
---
> i
diff diff-files/file2 second-diff-files/file2
2c2
< Hello
---
> ello

Der Befehl diff vergleicht nur Dateien in den Verzeichnissen der obersten Ebene, aber wenn Sie die Befehlszeilenoption -r (die für rekursive diff gilt) verwenden, werden Sie sehen, dass sogar die Dateien in Unterverzeichnissen verglichen werden:

$ diff -r diff-files/ second-diff-files/
diff -r diff-files/file1 second-diff-files/file1
1c1
< Hi
---
> i
diff -r diff-files/file2 second-diff-files/file2
2c2
< Hello
---
> ello
diff -r diff-files/more-diff-files/file1 second-diff-files/more-diff-files/file1
1c1
< Hi
---
> i
diff -r diff-files/more-diff-files/file2 second-diff-files/more-diff-files/file2
2c2
< Hello
---
> ello

8. Abwesende Dateien als leer behandeln

Der Befehl diff bietet auch eine Option, mit der Sie das Tool anweisen können, fehlende Dateien als leer zu behandeln. Wenn Sie beispielsweise file1 mit file3 vergleichen (das nicht existiert), ist das Standardverhalten von diff, einen Fehler zu erzeugen:

$ diff file1 file3
diff: file3: No such file or directory

Das ist nicht per se falsch, das macht in der Tat vollkommen Sinn. Aber es kann Fälle geben, in denen – in denen Sie nicht wollen, dass der Befehl diff den Fehler für solche Situationen auslöst (während Sie Teil eines Bash-Skripts sind, kann es sein?), dann können Sie für diese Szenarien die Befehlszeilenoption -N verwenden, die den Befehl zwingt, fehlende Dateien als leer zu behandeln und mit dem Vergleich fortzufahren.

$ diff -N file1 file3
1,5d0
< Hi
< 
< Helllo
< 
< Bye

Fazit

Wenn Sie beide Teile dieser Tutorial-Serie richtig durchgehen und alle Beispiele, die die Artikel enthalten, üben, dann wird es nicht lange dauern zu sagen, dass Sie am Ende einen guten Überblick über das Tool haben werden. Natürlich konnten wir in dieser Serie nicht alles diskutieren, was mit Diff zu tun hat, aber seien Sie versichert, dass viele der wichtigen Features/Funktionalitäten abgedeckt wurden.

Für diejenigen, die mehr über das Dienstprogramm erfahren möchten, ist die Man Page immer für dich da. Und ganz zu schweigen davon, dass Sie das Tool weiterhin häufig mit verschiedenen Dateisets verwenden sollten, um verschiedene Anwendungsfälle zu simulieren.

Das könnte Dich auch interessieren …