So verwenden Sie die Linux-Befehle cat und tac

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?“