Die Befehle cat
und tac
dienen zwar primär der Anzeige von Textdateiinhalten, doch sie bergen mehr Potenzial, als man auf den ersten Blick vermuten würde. Lassen Sie uns tiefer in die Materie eintauchen und einige nützliche Tricks für die Linux-Befehlszeile erkunden.
Diese zwei scheinbar simplen Befehle werden oft unterschätzt. Doch wer ihre vielfältigen Anwendungsmöglichkeiten kennt, wird schnell feststellen, dass sie bei der Bearbeitung von Dateien eine beträchtliche Arbeitslast übernehmen können.
Der Befehl `cat`
cat
wird in der Regel dazu verwendet, den Inhalt von Textdateien anzuzeigen und Teile von Dateien zu einer größeren Datei zusammenzufügen.
In früheren Zeiten, als die Modem-Verbindung die Regel war, wurden Binärdateien oft in kleinere Fragmente aufgeteilt, um den Download zu vereinfachen. Anstatt einer einzigen großen Datei, wurden mehrere kleine Dateien heruntergeladen. Wenn eine Datei fehlerhaft war, konnte sie einfach erneut angefordert werden.
Um die vielen kleinen Dateien wieder zu einer funktionierenden Binärdatei zusammenzufügen, benötigte man einen Mechanismus. Dieser Prozess wurde als Verkettung bezeichnet. Hier kam cat
ins Spiel und verdankte diesem Prozess seinen Namen.
Breitband- und Glasfaserverbindungen haben diesen Bedarf weitgehend obsolet gemacht. Was bleibt also für cat
heute zu tun? Eine ganze Menge, wie sich zeigen wird.
Textdateien anzeigen
Mit folgendem Befehl gibt cat
den Inhalt einer Textdatei im Terminalfenster aus:
cat datei.txt
Achten Sie darauf, dass die Datei auch tatsächlich eine Textdatei ist. Der Versuch, eine Binärdatei im Terminal anzuzeigen, kann zu unvorhersehbaren Ergebnissen führen. Im schlimmsten Fall kann die Terminalsitzung blockieren.
Hier ein Beispiel mit einer Datei namens `gedicht1.txt`:
Das ist nur ein Teil des Gedichts. Der Rest befindet sich in einer Datei `gedicht2.txt`. cat
kann den Inhalt mehrerer Dateien mit einem einzigen Befehl anzeigen, indem man sie in der Befehlszeile auflistet:
cat gedicht1.txt gedicht2.txt
Nun haben wir das gesamte Gedicht.
`cat` mit `less` verwenden
Das Gedicht wurde zwar vollständig ausgegeben, ist aber zu schnell durch das Terminalfenster gerollt, um es in Ruhe zu lesen. Mit einer Umleitung der Ausgabe von cat
zu less
können wir den Text in unserem eigenen Tempo durchgehen:
cat gedicht1.txt gedicht2.txt | less
So können wir durch den Text vor- und zurückblättern, obwohl dieser in zwei separaten Dateien gespeichert ist.
Zeilen in einer Datei nummerieren
Wir können die Zeilen in einer Datei bei der Anzeige nummerieren. Dazu verwenden wir die Option `-n` (Nummer):
cat -n gedicht1.txt
Die Zeilen werden nummeriert, so wie sie im Terminalfenster erscheinen.
Leerzeilen nicht nummerieren
Wir können die Zeilen nummerieren, aber die Leerzeilen zwischen den Versen werden ebenfalls gezählt. Um die Textzeilen zu nummerieren, Leerzeilen jedoch zu ignorieren, verwenden wir die Option `-b` (Nummer-Nicht-Leerzeichen):
cat -b gedicht1.txt
Jetzt werden nur die Textzeilen nummeriert.
Mehrere Leerzeilen nicht anzeigen
Wenn eine Datei Abschnitte mit aufeinanderfolgenden Leerzeilen enthält, können wir cat
anweisen, alle bis auf eine Leerzeile zu ignorieren. Betrachten wir diese Datei:
Der nächste Befehl bewirkt, dass cat
nur eine Leerzeile aus jedem Leerzeilenblock anzeigt. Dazu verwenden wir die Option `-s` (squeeze-blank):
cat -s gedicht1.txt
Dies hat keinen Einfluss auf den Inhalt der Datei selbst, sondern nur auf die Art und Weise, wie sie von cat
angezeigt wird.
Tabulatoren anzeigen
Wenn man herausfinden möchte, ob Leerzeichen durch Tabulatoren oder Leerzeichen entstanden sind, kann dies mit der Option `-T` (show-tabs) geschehen:
cat -T gedicht1.txt
Tabulatoren werden durch das Zeichen `^I` dargestellt.
Zeilenenden anzeigen
Mit der Option `-E` (show-ends) kann man nach zusätzlichen Leerzeichen am Zeilenende suchen:
cat -E gedicht1.txt
Zeilenenden werden durch das Zeichen `$` markiert.
Dateien verketten
Es ist nicht sinnvoll, ein Gedicht in zwei Dateien mit jeweils der Hälfte aufzubewahren. Lasst uns sie zusammenführen und eine neue Datei erstellen, die das gesamte Gedicht enthält:
cat gedicht1.txt gedicht2.txt > gedicht_gesamt.txt
Prüfen wir die neue Datei mit cat
:
cat gedicht_gesamt.txt
Die neue Datei enthält den Inhalt der beiden anderen Dateien.
Text an eine bestehende Datei anhängen
Das ist gut, aber eigentlich ist es noch nicht das ganze Gedicht. Der letzte Vers fehlt. Der letzte Vers ist der gleiche wie der erste Vers.
Wenn wir den ersten Vers in einer Datei haben, können wir ihn an das Ende von `gedicht_gesamt.txt` anhängen, und wir haben das vollständige Gedicht.
Im nächsten Befehl verwenden wir `>>` statt nur `>`. Mit einem einzelnen `>` würden wir `gedicht_gesamt.txt` überschreiben. Das wollen wir nicht. Wir möchten Text an das Ende anhängen.
cat erster_vers.txt >> gedicht_gesamt.txt
Überprüfen wir den Inhalt von `gedicht_gesamt.txt`:
cat gedicht_gesamt.txt
Endlich sind alle Teile des Gedichts zusammen.
Umleitung von `stdin`
Mit cat
kann man auch Eingaben von der Tastatur in eine Datei umleiten. Alles, was man eingibt, wird in die Datei umgeleitet, bis man `Strg+D` drückt. Hier verwenden wir ein einzelnes `>` da wir die Datei erstellen (oder überschreiben wollen, falls sie bereits existiert):
cat > mein_gedicht.txt
Sobald man den Befehl eingegeben hat, kann man mit der Eingabe beginnen. Mit `Strg+D` beenden wir die Eingabe. Wir können dann den Inhalt der neuen Datei mit folgendem Befehl überprüfen:
cat mein_gedicht.txt
Dieses Geräusch wie eine ferne Turbine ist wahrscheinlich Lewis Carroll, der sich in seinem Grab dreht.
Der Befehl `tac`
tac
ist ähnlich wie cat
, gibt aber den Inhalt von Dateien in umgekehrter Reihenfolge aus.
Sehen wir es uns an:
tac mein_gedicht.txt
Die Datei wird in umgekehrter Reihenfolge im Terminalfenster ausgegeben. In diesem Fall hat dies keinen Einfluss auf ihren literarischen Wert.
`tac` mit `stdin` verwenden
Wird `tac` ohne Dateinamen verwendet, reagiert es auf Eingaben von der Tastatur. Wenn man `Strg+D` drückt, stoppt die Eingabephase und `tac` listet auf, was man eingegeben hat, allerdings in umgekehrter Reihenfolge:
tac
Wenn `Strg+D` gedrückt wird, wird die Eingabe umgekehrt und im Terminalfenster ausgegeben.
`tac` mit Protokolldateien verwenden
Kann `tac` neben diesen Spielereien auch etwas Nützliches tun? Ja, das kann er. Viele Protokolldateien fügen ihre neuesten Einträge am Ende der Datei ein. Mit `tac` (und paradoxerweise `head`) können wir den letzten Eintrag ins Terminalfenster holen.
Wir verwenden `tac`, um die Syslog-Datei in umgekehrter Reihenfolge aufzulisten und diese Ausgabe an `head` weiterzuleiten. Indem wir `head` anweisen, nur die erste empfangene Zeile auszugeben (welche dank `tac` die letzte Zeile der Datei ist), sehen wir den neuesten Eintrag in der Syslog-Datei.
tac /var/log/syslog | head -1
`head` gibt den neuesten Eintrag aus der Syslog-Datei aus und beendet sich anschließend.
Beachten Sie, dass `head` nur eine Zeile ausgibt – wie wir angefordert haben – aber die Zeile ist so lang, dass sie zweimal umbrochen wird. Deshalb sieht es im Terminalfenster wie drei Ausgabenzeilen aus.
`tac` mit Textdatensätzen verwenden
Der letzte Trick, den `tac` im Ärmel hat, ist besonders nützlich.
Normalerweise arbeitet `tac` mit Textdateien, indem es sie Zeile für Zeile von unten nach oben abarbeitet. Eine Zeile ist eine Folge von Zeichen, die durch ein Zeilenumbruchzeichen abgeschlossen wird. Wir können `tac` aber auch anweisen, mit anderen Trennzeichen zu arbeiten. So können wir „Datenblöcke“ innerhalb einer Textdatei als Datensätze behandeln.
Nehmen wir an, wir haben eine Protokolldatei eines Programms, die wir überprüfen oder analysieren müssen. Betrachten wir das Format mit `less`:
less logdatei.dat
Wie man sehen kann, hat die Datei ein sich wiederholendes Format. Es gibt Folgen von jeweils drei Zeilen mit hexadezimalen Werten. Jeder Satz von drei hexadezimalen Zeilen hat eine Beschriftungszeile, die mit „=SEQ“ beginnt, gefolgt von einer Ziffernfolge.
Wenn wir zum Ende der Datei scrollen, sehen wir, dass viele solcher Datensätze vorhanden sind. Der letzte hat die Nummer 865.
Nehmen wir an, wir müssen diese Datei aus irgendeinem Grund in umgekehrter Reihenfolge, Datensatz für Datensatz, bearbeiten. Die Zeilenreihenfolge der drei hexadezimalen Zeilen in jedem Datensatz muss erhalten bleiben.
Beachten Sie, dass die letzten drei Zeilen der Datei mit den Hexadezimalwerten 93, E7 und B8 in dieser Reihenfolge beginnen.
Lassen Sie uns `tac` verwenden, um die Datei umzukehren. Es ist eine sehr lange Datei, daher leiten wir sie an `less` um.
tac logdatei.dat | less
Das kehrt die Datei um, aber es ist nicht das Ergebnis, das wir wollen. Wir möchten, dass die Datei umgekehrt wird, aber die Zeilen in jedem Datensatz in ihrer ursprünglichen Reihenfolge bleiben.
Wir haben vorher aufgezeichnet, dass die letzten drei Zeilen in der Datei mit den Hexadezimalwerten 93, E7 und B8 beginnen, in dieser Reihenfolge. Die Reihenfolge dieser Zeilen wurde umgekehrt. Außerdem befinden sich die Zeilen „=SEQ“ nun unter jedem Satz von drei hexadezimalen Zeilen.
`tac` eilt zur Rettung.
tac -b -r -s ^=SEQ.+[0-9]+*$ logdatei.dat | less
Lasst uns das aufschlüsseln.
Die Option `-s` (Separator) teilt `tac` mit, was wir als Trennzeichen zwischen unseren Datensätzen verwenden wollen. Sie weist `tac` an, nicht das übliche Newline-Zeichen, sondern unser Trennzeichen zu verwenden.
Die Option `-r` (regex) weist `tac` an, die Trennzeichenfolge als regulären Ausdruck zu behandeln.
Die Option `-b` (before) bewirkt, dass `tac` das Trennzeichen vor jedem Datensatz auflistet und nicht danach (was die übliche Position des Trennzeichens, des Zeilenumbruchzeichens, ist).
Die Zeichenfolge `-s` (Trennzeichen) ^=SEQ.+[0-9]+*$ wird wie folgt entschlüsselt:
Das Zeichen `^` steht für den Zeilenanfang. Darauf folgt `=SEQ.+[0-9]+*$`. Damit wird `tac` angewiesen, nach jeder Vorkommen von „=SEQ“ am Zeilenanfang zu suchen, gefolgt von einer beliebigen Ziffernfolge (gekennzeichnet durch `[0-9]`) und gefolgt von einem beliebigen Zeichensatz (gekennzeichnet durch `*`).
Wir leiten das Ganze wie üblich an `less` weiter.
Unsere Datei wird nun in umgekehrter Reihenfolge angezeigt, wobei jede „=SEQ“-Labelzeile vor ihren drei Zeilen mit Hexadezimaldaten steht. Die drei Zeilen mit hexadezimalen Werten befinden sich innerhalb jedes Datensatzes in ihrer ursprünglichen Reihenfolge.
Wir können dies einfach überprüfen. Der erste Wert der ersten drei hexadezimalen Zeilen (das waren die letzten drei Zeilen, bevor die Datei umgekehrt wurde) stimmt mit den zuvor aufgezeichneten Werten überein: 93, E7 und B8, in dieser Reihenfolge.
Das ist ein ziemlicher Trick für einen Befehl in einem Terminalfenster.
Alles hat einen Zweck
In der Linux-Welt können selbst die scheinbar einfachsten Befehle und Dienstprogramme überraschende und leistungsstarke Funktionen haben.
Die Designphilosophie von einfachen Dienstprogrammen, die eine Sache gut machen und problemlos mit anderen Dienstprogrammen zusammenarbeiten, hat zu einigen seltsamen Befehlen wie `tac` geführt. Auf den ersten Blick wirkt er ein bisschen seltsam. Aber wenn man unter die Oberfläche blickt, findet man eine unerwartete Leistung, die man zu seinem Vorteil nutzen kann.
Oder, wie eine andere Philosophie sagt: „Verachte die Schlange nicht, weil sie keine Hörner hat, denn wer sagt, dass sie kein Drache werden soll?“