Mit Diff Unterschiede in Dateien aufspüren

Aus LinuxUser 02/2020

Mit Diff Unterschiede in Dateien aufspüren

© Damedeeso, 123RF

Spurensuche

Welche Version einer Datei liegt vor? Die richtigen Tools beantworten diese Frage mit nur einem Kommando.

Gleich von Anfang an lohnt es sich, mit der alten Mär aufzuräumen, dass Sie Unterschiede zwischen Dateien bereits an deren Größe erkennen. Das mag gelegentlich stimmen, aber eine Garantie dafür gibt es nicht. Listing 1 zeigt drei gleich große Dateien. In 2.txt unterscheidet sich aber in einer Zeile die Schreibweise der Zeichen: ABCdef statt abcDEF. Verlassen Sie sich also nicht auf die Abfrage von Metadaten.

Listing 1

$ ls -l
-rw-r--r-- 1 artikel artikel 60 Nov  9 08:59 1.txt
-rw-r--r-- 1 artikel artikel 60 Nov  9 08:59 2.txt
-rw-r--r-- 1 artikel artikel 60 Nov  9 08:59 3.txt

Beispieldaten

Als Datenbasis für die Beispiele in diesem Beitrag dienen als Textdateien die Files 1.txt, 2.txt und 3.txt, wobei 1.txt und 3.txt identisch sind. Außerdem kommen die PDF-Dateien 1.pdf, 2.pdf und 3.pdf zum Einsatz, wobei wiederum 1.pdf und 3.pdf identisch sind. Die Dateien befinden sind in den Verzeichnissen erstes, zweites und drittes, wobei der Inhalt von erstes und drittes gleich ist.

Übersicht

Die Diff-Tools eignen sich für den Einsatz in Shell-Skripten oder die Arbeit auf dem Desktop. Manche Programme vergleichen nur Textdateien, wobei die Möglichkeiten trotzdem vielfältig ausfallen: Von Quelltext über Markup-Dateien bis hin zu strukturierten Textdateien im CSV-Format eignen sich zahlreiche Varianten als Ausgangsmaterial. Andere Tools bearbeiten sogar Binärdateien. Die Tabelle “Diff-Kommandos” zeigt eine Auswahl der Befehle.

Befehl

vergleicht

Hinweise

diff

Textdateien, Verzeichnisinhalte, Binärdateien

für Shell-Skripte geeignet

numdiff

Textdateien (mit numerischem Inhalt)

für Shell-Skripte geeignet

duff

Textdateien/Binärdateien/Verzeichnisinhalte

listet nur Duplikate auf, für Shell-Skripte geeignet

fcomp

Textdateien/Binärdateien

für Shell-Skripte geeignet, eventuell weitere Hilfsmittel notwendig

icdiff

Textdateien

für Shell-Skripte geeignet, eventuell weitere Hilfsmittel notwendig

difference

Zeichenketten

Für Shell-Skripte geeignet, weitere Hilfsmittel wie Wc notwendig

latexdiff

Latex-Dateien

im Shell-Skript, weitere Hilfsmittel notwendig

ssh-diff

Dateien per SSH

für Shell-Skripte bedingt geeignet, weitere Hilfsmittel notwendig

vbindiff

Binär- und Textdateien

Shell, benutzergeführt

comparepdf

PDF-Dateien

für Shell-Skripte geeignet

diffpdf

PDF-Dateien

GUI, benutzergeführt

diffimg

Bilddateien

Formate: PNG, GIF, JPEG, Vergleich PS mit GS

diffuse

Textdateien

GUI, benutzergeführt

meld

Textdateien

GUI, benutzergeführt

Generalist

Als universelles Werkzeug eignet sich Diff besonders für den Einsatz in einem Shell-Skript. Dieses Programm findet sich praktisch auf allen Linux- und BSD-Systemen. Abbildung 1 zeigt den Einsatz in der Shell mit Abfrage des Exit-Codes. Dabei steht der Rückgabewert 0 für zwei identische, 1 für unterschiedliche Dateien oder Verzeichnisse. Die Option -q unterdrückt umfangreiche Ausgaben. Abbildung 2 zeigt den Vergleich zweier PDF-Dateien und zweier Verzeichnisse.

Abbildung 1: Der Vergleich zweier Textdateien mit Diff, wobei der Exit-Code bereits Auskunft über mögliche Unterschiede gibt.

Abbildung 1: Der Vergleich zweier Textdateien mit Diff, wobei der Exit-Code bereits Auskunft über mögliche Unterschiede gibt.


Abbildung 2: Beim Vergleich anderer Dateitypen und von Verzeichnissen leistet Diff ebenfalls gute Dienste.

Abbildung 2: Beim Vergleich anderer Dateitypen und von Verzeichnissen leistet Diff ebenfalls gute Dienste.

Mit der Option -s weisen Sie Diff an, identische Dateien anzuzeigen. Das erleichtert das Aufspüren von Duplikaten. Listing 2 zeigt, wie Sie eine Tabelle erzeugen, die zu jedem Objekt gegebenenfalls auch das Duplikat aufzählt.

Listing 2

#! /bin/bash
# Positionsparameter: $1 = Verzeichnis
if [ -z $1 ]; then
  echo "Eingabe: Listing1.sh VERZEICHNIS"
  exit
fi
cd $1
# Duplikate mit Fiff finden
for i in $(ls -1); do
  for k in $(ls -1 | sort -r); do
    if [ "$i" = "$k" ]; then
      # Falls Vergleich eines Objekts mit
      # sich selbst, gehe ans Schleifenende
      continue
    fi
    diff -sq $i $k 2> /dev/null | grep -v "diff:" | grep identisch
  done
done
cd

Abbildung 3 zeigt den Ablauf mit den Musterdaten. Die Liste fällt in anderen Fällen unter Umständen sehr umfangreich aus, da das Skript dann eventuell sogar Dateien in Unterverzeichnissen miteinander vergleicht.

Abbildung 3: Das Skript aus <a href="#artRef-l2">Listing&nbsp;2</a> untersucht eine Reihe von Dateien und zeigt an, ob sie sich unterscheiden oder identisch sind.

Abbildung 3: Das Skript aus Listing 2 untersucht eine Reihe von Dateien und zeigt an, ob sie sich unterscheiden oder identisch sind.

Duplikate finden

Speziell zum Auflisten von doppelten Inhalten eignet sich Duff. Sie übergeben dem Kommando ein Suchmuster, damit die Suche gelingt, also mindestens *. Von Haus aus unterbleibt der Vergleich von Unterverzeichnissen, außer Sie fordern das explizit mit der Option -r an. Beim Einsatz in einem Shell-Skript benötigen Sie nur die Angabe der Duplikate selbst, was Sie mittels -e anfordern.

Abbildung 4 stellt die Grundfunktionen anschaulich dar. Zuerst finden Sie die “Grundform”. Anzahl der übereinstimmenden Dateien, Original- und Duplikat-Datei werden aufgelistet. Die Anzeige von Duplikaten bei den Textdateien im aktuellen Verzeichnis zeigt das zweite Beispiel, zum Schluss sehen Sie den Vergleich aller Dateien und Verzeichnisse mit der Auflistung der Duplikate.

Abbildung 4: Mit Duff geht die Suche nach Duplikaten noch leichter, da die Software genau auf diesen Zweck zugeschnitten ist.

Abbildung 4: Mit Duff geht die Suche nach Duplikaten noch leichter, da die Software genau auf diesen Zweck zugeschnitten ist.

Nachdem Duff speziell Duplikate aufspürt, liegt der Einsatz in einem Skript nahe. In Listing 3 finden Sie ein Skript, das Duplikate mit oder ohne Rückfrage entfernt. Die Rückfrage erhalten Sie durch die Option -i beim Befehl rm. Abbildung 5 zeigt, wie das in der Praxis aussieht.

Listing 3

#! /bin/bash
# Löschen von Duplikaten
echo "Gefundene Duplikate:"
duff -re .
echo "------------------------------------"
read -p "Alle löschen (A), Löschen mit Nachfrage (f), ABBRUCH (ENTER) " we
if [ -z $we ]; then
  echo "Keine Aktion gewählt"
  exit
fi
if [ "$we" = "A" ]; then
  for i in $(duff -re .); do
    rm -rv $i
  done
fi
if [ "$we" = "f" ]; then
  for i in $(duff -re .); do
    rm -rvi $i
  done
fi

Abbildung 5: Wollen Sie Duplikate aus einem Verzeichnis entfernen, eignet sich dazu eine Kombination aus Duff mit etwas Shell-Logik.

Abbildung 5: Wollen Sie Duplikate aus einem Verzeichnis entfernen, eignet sich dazu eine Kombination aus Duff mit etwas Shell-Logik.

Zeichenketten vergleichen

Das Shell-Builtin test leistet meist gute Dienste beim Vergleichen von Zeichenketten (Listing 4). Für einen schnellen Vergleich ist so ein Konstrukt jedoch umständlich. Mit Difference gelingt das Auswerten zweier Strings übersichtlicher. Abbildung 6 zeigt die Arbeitsweise des Tools.

Listing 4

if [ "$HOME" = "$PWD" ]; then
  echo "Aktuelles Verzeichnis ist das Heimatverzeichnis"
else
  echo "Aktuelles Verzeichnis ist nicht das Heimatverzeichnis"
fi

Abbildung 6: Difference hilft Ihnen dabei, Zeichenketten auf die Schnelle zu vergleichen.

Abbildung 6: Difference hilft Ihnen dabei, Zeichenketten auf die Schnelle zu vergleichen.

Um dieses Programm in ein Skript einzubinden, bietet sich der Befehl wc zum Auswerten des Ergebnisses an. Listing 5 zeigt ein sehr reduziertes Beispiel; Abbildung 7 gibt einen Eindruck vom Ablauf des Skripts.

Listing 5

#! /bin/bash
# Minimalistischer Zeichenkettenvergleich
read -p "1. Eingabe: " a
read -p "2. Eingabe: " b
c=$(difference $a $b | wc -w)
if [ $c -eq 1 ]; then
  echo "Beide Eingaben sind identisch"
elif [ $c -gt 1 ]; then
  echo "Die Eingaben unterscheiden sich"
fi

Abbildung 7: Der Vergleich von zwei Zeichenketten ist eine Aufgabe, die Sie mit dem Tool Difference auf vergleichsweise einfache Weise erledigen.

Abbildung 7: Der Vergleich von zwei Zeichenketten ist eine Aufgabe, die Sie mit dem Tool Difference auf vergleichsweise einfache Weise erledigen.

Mehr Komfort

Etwas mehr Komfort bietet das Programm Icdiff. Beim Vergleich zweier Textdateien hebt es Unterschiede farblich hervor, beim Vergleich zweier Verzeichnisse erhalten Sie eine Liste mit den Unterschieden.

Wenn Sie die Ergebnisse von Icdiff in einem Shell-Skript auswerten möchten, benötigen Sie eine Kombination aus mehreren Tools, die Sie über eine Pipe verbinden. Abbildung 8 zeigt den Vergleich von Dateien und Verzeichnissen, jeweils abweichend und übereinstimmend.

Abbildung 8: Icdiff bringt beim Vergleich von Dateien und Verzeichnissen Farbe ins Spiel.

Abbildung 8: Icdiff bringt beim Vergleich von Dateien und Verzeichnissen Farbe ins Spiel.

Auf anderen Rechnern

Der Vergleich von Text- und Binärdateien, die sich auf verschiedenen Rechnern befinden oder verschiedenen Benutzern auf einem System gehören, erfordert ein etwas anderes Handwerkszeug: Ssh-diff versteht die von Diff bekannten Optionen mit Ausnahme von -r.

Für den Aufbau der Verbindung dürfen Sie außerdem einen abweichenden Port beim Zielsystem angeben, und bei Bedarf beschränken Sie die Kommunikation auf IPv4 oder IPv6. Das Kennwort geben Sie doppelt ein, es sei denn, Sie arbeiten mit einer Authentifizierung, die auf passwortlosen Schlüsseln basiert.

Beim Vergleich von Binärdateien liefert Ssh-diff die Meldung, dass sich die Dateien unterscheiden. Abbildung 9 zeigt den Vergleich einer Textdatei. Im ersten Anlauf kommen in dem Beispiel zwei unterschiedliche, im zweiten zwei identische Dateien zum Einsatz.

Abbildung 9: Beim Vergleich mit Ssh-diff brauchen die Dateien nicht auf demselben Rechner zu liegen. Das Tool setzt aber SSH als Grundlage voraus.

Abbildung 9: Beim Vergleich mit Ssh-diff brauchen die Dateien nicht auf demselben Rechner zu liegen. Das Tool setzt aber SSH als Grundlage voraus.

PDF-Dateien

Für den Vergleich zweier PDF-Dateien per Shell eignet sich Comparepdf. Die Tabelle “Comparepdf-Optionen” zeigt die wenigen Optionen des Werkzeugs. Bei Gleichheit lautet der Exit-Code 0, andernfalls ist er größer null. Ein entsprechender Vergleich würde zwar auch mit Diff und Duff klappen, fiele aber komplexer aus.

Option

Aktion

-ct

Text vergleichen (Standard)

-ca

grafischer Vergleich (für Scans)

-v=0

Ausgabe im Terminal unterdrücken

-v=1

Ausgabe bei Unterschied

-v=2

vollständige Ergebnisse anzeigen

Abbildung 10 zeigt den Einsatz von Comparepdf in der Shell. Durch den eindeutigen Exit-Code benötigen Sie keine Werkzeuge, um in einem Shell-Skript das Ergebnis tiefer auszuwerten.

Abbildung 10: PDF-Dateien mit <code>comparepdf</code> vergleichen.

Abbildung 10: PDF-Dateien mit comparepdf vergleichen.

Möchten Sie die Unterschiede zwischen zwei PDF-Dateien am Bildschirm sehen, greifen Sie zu Diffpdf. Abbildung 11 zeigt einen Vergleich, bei dem Unterschiede zutage treten. Bei identischen PDF-Dateien erscheint anstelle des Texts nur in jedem Dateifenster der Hinweis, dass die Dateien identisch sind.

Abbildung 11: Diffpdf stellt unterschiedliche PDF-Dateien dar.

Abbildung 11: Diffpdf stellt unterschiedliche PDF-Dateien dar.

Bilder vergleichen

Bei Bildern helfen die bisher beschriebenen Werkzeuge nur bedingt weiter, da es sich um Binärdateien handelt. Benötigen Sie innerhalb eines Skripts einen entsprechenden Exit-Code, ist das Prüfen gegen eine Checksumme praktikabler.

Sind Hinweise auf die Änderungen selbst von Interesse, hilft Ihnen Diffimg weiter. Das Programm verarbeitet Bilddateien in den Formaten PNG, GIF und JPEG. Postscript-Dateien bearbeiten Sie unter Zuhilfenahme von Ghostscript. Es gibt keine Optionen, die Syntax fällt recht einfach aus (Listing 6).

Listing 6

$ diffimg Datei1 Datei2 Differenzbild

Wenn Sie das Differenzbild öffnen, finden Sie die abweichenden Pixel angezeigt. So decken Sie etwas subtile Änderungen auf, wie etwa im Beispiel aus Abbildung 12: Dort ist die Nummer der Lokomotive im RHB-Bahnhof Guarda (Graubünden) im mittleren Bild mit der Hintergrundfarbe des Zugs überpinselt. Das Ergebnis mit der Gegenüberstellung sehen Sie links. Stimmen beide Dateien überein, erhalten Sie eine vollständig schwarze Ausgabedatei, Änderungen finden Sie lagerichtig als weiße Pixel.

Abbildung 12: Links sehen Sie das Original, in der Mitte das bearbeitete Bild, rechts die Ausgabe der Differenzen der beiden Bilder, wobei die hellen Pixel die Lage der &Auml;nderungen anzeigen.

Abbildung 12: Links sehen Sie das Original, in der Mitte das bearbeitete Bild, rechts die Ausgabe der Differenzen der beiden Bilder, wobei die hellen Pixel die Lage der Änderungen anzeigen.

Steganografische Bilder, also solche, die eine versteckte Nachricht beinhalten, weisen als Differenz willkürliche, einzelne Pixel über die gesamte sonst schwarze Fläche des Differenzbilds auf. Das Verschlüsselungsrätsel selbst lösen Sie damit allerdings nicht. Daher ist es beim Gebrauch von Steganografie wichtig, die Originaldateien zum einen selbst zu erstellen und zum anderen nach dem Einsatz als Träger sicher zu löschen, um einen Vergleich auszuschließen.

Differenzen einpflegen

Beim Übertragen von Dateien brauchen Sie nicht zwingend den gesamten Inhalt zu übermitteln, wenn frühere Versionen am Ziel bereits vorliegen. Egal, ob Manuskript oder Quelltext: Es genügt, die Differenz zu finden und diese zu transferieren.

Mit vielen Programmen, meist aber mit Diff, erstellen Sie eine Datei mit den Patch-Anweisungen, um Änderungen einzuspielen. Mit der Anweisung aus der ersten Zeile von Listing 7 erstellen Sie eine Patch-Datei, deren Inhalt für unser Beispiel Listing 8 zeigt.

Listing 7

$ diff -uNr Alter_Stand Neuer_Stand > Patch-Datei
$ patch -b Alter_Stand < Patch-Datei

Listing 8

--- 1.txt       2019-11-09 08:59:06.000000000 +0100
+++ 2.txt       2019-11-09 08:59:13.000000000 +0100
@@ -1,4 +1,4 @@
 Das ist eine Textdatei.
 Sie besteht aus
 drei Zeilen!
-abcDEF
+ABCdef

Damit sind die Dateinamen und die enthaltenen Änderungen bekannt. Sie spielen die Daten mit dem Kommando aus der zweiten Zeile von Listing 7 ein. Mit der Option -b sichern Sie dabei die Originaldatei vor dem Patch. Abbildung 13 zeigt das Anfertigen der Patch-Datei.

Abbildung 13: Gerade bei Quellcode ist es sinnvoll, lediglich die Differenzen zu einer fr&uuml;heren Datei als sogenannten Patch bereitzustellen. Dessen Gr&ouml;&szlig;e ist meist weitaus geringer, was beim &Uuml;bertragen &uuml;bers Netz Vorteile bringt.

Abbildung 13: Gerade bei Quellcode ist es sinnvoll, lediglich die Differenzen zu einer früheren Datei als sogenannten Patch bereitzustellen. Dessen Größe ist meist weitaus geringer, was beim Übertragen übers Netz Vorteile bringt.

Abbildung 14 zeigt das Einspielen des Patches und das Ergebnis. Dabei fragt die Software ab, ob Sie die neuere Datei bearbeiten möchten.

Abbildung 14: Das Einspielen eines Patches gelingt im Handumdrehen.

Abbildung 14: Das Einspielen eines Patches gelingt im Handumdrehen.

Auch das Patchen von Verzeichnissen gelingt bei Bedarf. Dazu erstellen Sie mittels Diff eine Datei mit den Unterschieden, die Sie mit Patch wieder einspielen.

Fazit

Auf der Kommandozeile lassen sich Unterschiede zwischen Dateien und Verzeichnissen schnell ermitteln. Umgekehrt erkennen Sie auf einfache Weise doppelt Vorhandenes. Statt immer komplette Textdateien weiterzugeben, sparen Sie bei umfangreichen Änderungen Bandbreite und Plattenplatz, indem Sie jeweils einen Patch erstellen und ihn weiterreichen. 

Der Autor

Harald Zisler beschäftigt sich seit den frühen 90er-Jahren mit FreeBSD und Linux. Zu Technik- und EDV-Themen verfasst er Zeitschriftenbeiträge und Bücher.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDF
LinuxUser 02/2020 KAUFEN
EINZELNE AUSGABE
ABONNEMENTS
TABLET & SMARTPHONE APPS
E-Mail Benachrichtigung
Benachrichtige mich zu:

Hinweis: Dieser Artikel ist älter als ein Jahr, enthaltene Informationen sind möglicherweise veraltet.

0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben