UNIX Kommandos verkoppeln
aus: Wie werde ich UNIX-Guru
und: UNIX-Das umfassende Handbuch
Willemers Informatik-Ecke

Jedes Programm erledigt genau seine Aufgabe

UNIX-Kommandos wirken manchmal etwas spartanisch. Ihre Ausgaben sind nur auf das beschränkt, was ihre Aufgabe ist. Während ls wirklich nur die Dateinamen anzeigt, zeigt der analoge Befehl dir unter MS-DOS gleich noch den Namen der Platte, die Anzahl der Dateien und wieviel Platz auf der Platte noch frei ist. Der Grund dafür liegt nicht in erster Linie in der Faulheit der UNIX-Programmierer, sondern darin, dass es zur UNIX-Philosophie gehört, Programme zu kombinieren, um die gewünschten Informationen zu erhalten. Die Daten, die ein Befehl erzeugt, sollten so gestaltet sein, dass sie von einem anderen Programm weiterverarbeitet werden.

Programme kombinieren

Um auf das Beispiel mit der Anzahl der Dateien zurückzukommen, würde man unter UNIX das Ergebnis von ls durch den Befehl wc (wordcounter. Das Programm zählt Worte.), bearbeiten lassen und erhielte damit die Anzahl der aufgelisteten Dateien. Das Kommando dazu sieht so aus:

ls | wc

Als Kupplung zwischen den Befehlen wird die Ein- und Ausgabe der Programme verwendet. Unter UNIX kann beides leicht umgeleitet und aneinander gehängt werden. Hier wird die Ausgabe von ls in die Eingabe von wc geschoben. Der senkrechte Strich soll eine Röhre (engl. pipe) darstellen.

Ein- und Ausgabe als Datenstrom

Ein- und Ausgabe sind Dateien

Die Tastatureingabe und die Bildschirmausgabe wird unter UNIX jeweils als Datei aufgefasst. Die Standardeingabe heißt stdin und die Ausgabe stdout. Um von der Tastatur ein Dateiende simulieren zu können, wird die Tastenkombination ctrl-D am Anfang der Zeile verwendet.

ctrl-D ist die Dateiendekennung

Das ctrl-D ist bereits vom Abmelden her bekannt. Tatsächlich erwartet die Shell aus der Standardeingabedatei ihre Befehle und beendet sich, wenn diese Datei beendet wird. Dieses Verhalten kann man natürlich dazu nutzen, mehrere Shellbefehle in eine Datei zu schreiben und sie am Stück ausführen zu lassen. Dazu ruft man die Shell mit dem Kommando sh und dieser Datei als Parameter auf. Die Zusammenstellung mehrerer Befehle ist bereits ein einfaches Programm. Abläufe, die immer gleich sind, kann man so leicht automatisieren. Mit solchen Programmen wird sich das Kapitel Shellprogrammierung befassen.

stderr: Kanal für Fehlermeldungen

Wie in den folgenden Abschnitten zu sehen ist, kann man stdout des einen Programmes und stdin eines anderen Programmes miteinander verkoppeln. Das zweite Programm verarbeitet also die Ausgaben des ersten Programms als seine Eingabe. Da Fehlermeldungen in diesem Datenstrom wenig hilfreich sind, gibt es neben stdout noch einen separaten Ausgabekanal für die Fehlermeldungen namens stderr. Normalerweise zeigt auch dieser auf das Terminal. Auf diese Weise kann man beliebig viele Programme aneinanderhängen, ohne sich allzu große Sorgen darüber machen zu müssen, was im Fehlerfall einer Komponente passiert. Die Fehlermeldung erscheint dennoch auf der Konsole, während im Datenstrom nur gültige und verarbeitbare Daten fließen.

Umleitung

Durch Anhängen von < meinedatei an einen Befehl wird der Inhalt der Datei meinedatei als Eingabe verwandt. Die Datei meinedatei wird also für das Programm zum stdin. Durch Anhängen von > meinedatei wird die Ausgabe auf die Datei meinedatei umgeleitet. Also wird wird die Datei meinedatei für das Programm zum stdout. Beides ist kombinierbar. Beispielsweise bedeutet

sort <eingabedatei  >ausgabedatei

dass die Datei eingabedatei als Eingabe für den Sortierbefehl verwendet wird und dass die Ergebnisse in der Datei ausgabedatei abgelegt werden.

cat >testdatei

Editor für Arme

Mit diesem Kommando kann man auch dann Textdateien erzeugen, wenn kein Editor verfügbar ist. Hier werden zwei Effekte ausgenutzt. Der erste ist die Umleitung der Ausgabe. Die Ausgabe von cat wird nicht am Bildschirm angezeigt, sondern in eine Datei geschrieben. Es wird also die Datei testdatei erzeugt. Der zweite Effekt ist, dass keine Eingabedatei für cat angegeben wird. Dementsprechend greift cat auf die Standardeingabe, nämlich die von der Tastatur zu. Es wird also solange von der Tastatur eingelesen, bis diese Eingabeeinheit am Ende der Datei ist. Das Ende der Datei wird bei der Tastatur mit ctrl-D erzeugt. Das Erzeugen von Dateien auf diese Weise ist natürlich hochgradig unbequem, da es kaum Korrekturmöglichkeiten gibt.

Datei stutzen

Beim Umleiten einer Ausgabe wird die Zieldatei zunächst geleert. Diesen Effekt kann man nutzen, wenn eine Protokolldatei zu groß wird. Da solche Dateien von anderen Prozessen beschrieben werden, kann man sie nicht einfach löschen. Auch wenn man die Datei unter diesem Namen wieder erzeugt, ist es nicht dieselbe Datei, die der Hintergrundprozess offen hatte. Mit dem Größerzeichen und dem Dateinamen wird die Datei sofort auf 0 Byte zurückgesetzt. Dabei ist die Datei nicht gelöscht worden. Es ist exakt die Datei, die der Hintergrundprozess im Zugriff hatte.

> /var/log/messages

>> hängt die Ausgabe an die Datei an

Nicht immer soll der Inhalt der Datei gelöscht werden, in die man die Ausgabe umleitet. Verwendet man statt einem Größerzeichen zwei, so wird die Ausgabe an die existierende Datei angehängt.

2> leitet stderr um

Um stderr umzuleiten, wird eine 2 vor das Größerzeichen geschrieben. Dies ist beispielsweise wichtig, wenn man die Fehlermeldungen eines Compilers in einer Datei auffangen will.

cc mistprogramm.c 2>fehlerliste

Um stdout und stderr in die gleiche Datei umzuleiten, gibt es je nach verwendeter Shell zwei Umleitungsoperatoren. Bei der Kornshell wird an das Größerzeichen ein kaufmännisches Und mit einer 1 angehängt. Bei der C-Shell wird nur das kaufmännische Und vor das Größerzeichen gestellt. Soll der Compiler des obigen Beispiels Fehlermeldungen und Ausgaben in dieselbe Datei umleiten lauten die alternativen Befehle:

cc mistprogramm.c 2>&1 fehlerliste
cc mistprogramm.c &> fehlerliste

/dev/null ist der Müllschlucker

Manchmal kann man mit den Ausgaben der Programme überhaupt nichts anfangen. Für solche Zwecke hat UNIX ein Datengrab oder Mülleimer, der /dev/null heißt. Alle Daten, die auf diese Pseudodatei umgeleitet werden, verschwinden auf Nimmerwiedersehen.

Piping

seitenweises Blättern

Durch den senkrechten Strich | wird eine Pipe aufgebaut, die die Ausgabe des links stehenden Kommandos auf die Eingabe des rechts stehenden Kommandos umleitet. Programme, die ihre Anwendung typischerweise im Datenstrom einer Pipe finden, nennt man Filter. Ein ganz typischer Filter ist das Programm more. Um sich längere Verzeichnisse seitenweise anzusehen, wird man eine Pipe zwischen ls -l und more verwenden:

ls -l | more

Bedienung des more

Nach jeder Bildschirmseite erscheint die Meldung more. Mit der Leertaste kann eine Seite weitergeblättert werden. Die Returntaste wirkt ein zeilenweises blättern. Will man die Ausgabe beenden, gibt man ein q ein.

Bindestrich als Dateiname

Einige Programme geben ihre Ergebnisse nicht auf stdout aus, sondern benutzen immer eine Ausgabedatei. Dazu gehört beispielsweise das Datensicherungsprogramm tar. tar schreibt normalerweise auf das Standardgerät zur Datensicherung. Auf Servern ist dies meist die Bandstation. Allerdings kann man tar mit der Option -f dazu bringen, in eine Datei zu schreiben. In bestimmten Situationen soll das Programm aber in eine Pipe schreiben. Damit in solchen Fällen eine Pipe hineingeschrieben werden kann, braucht man einen Dateinamen für die Pipe, den man für die Pipe statt des Dateinamens angeben kann. An dieser Stelle wird ein Bindestrich als Synonym für stdin und stdout verwendet. Diese Konstruktion ist beim Kopieren von Verzeichnisbäumen mit tar und beim Brennen von Verzeichnissen auf CD zu sehen.

Datenabzweigung: tee

Manchmal kann man in einer Pipe auch die Zwischenergebnisse gut gebrauchen. In diesem Fall kann man das Kommando tee gefolgt von einem Dateinamen in die Pipe einfügen. Dann wird der aktuelle Datenstrom in diese Datei abgezweigt, während trotzdem die nächste Anwendung in der Pipe den Datenstrom unverändert weiterverarbeiten kann. Beispiel:

ls | tee out | wc

In der Datei out wird man die Dateinamen des aktuellen Verzeichnisses finden, während die Ausgabe des Befehls die Anzahl der Dateien darstellt. Das Programm tee bildet also das T-Stück im Datenstrom und zweigt Daten in die angegebene Datei ab.

Verschachtelte Befehls-Argumente

Befehl im Befehl

Die Argumente eines Befehls können durch andere Prozesse erzeugt werden. Um dies zu erreichen, wird statt des Arguments ein Befehl in rückwärtige Hochkommata (backquotes) gesetzt werden. Von manchen UNIX Anwendern wird dieses Zeichen auch Rückwärtsdüdel genannt. Leider kann ich für die korrekte Schreibweise nicht garantieren. Auf amerikanischen Tastaturen liegt sie rechts neben dem Apostroph. Man findet diese Taste auf einer deutschen Tastatur rechts neben dem ß in Kombination mit der Hochstelltaste. Das Ergebnis dieses Befehls wird dem eigentlichen Befehl als Argument zugeführt. Beispiel:

ls -l `cat filelist`

In diesem Fall wird der Inhalt der Datei filelist mit cat ausgegeben und so als Argumentliste dem ls zugeführt. Man könnte die Datei filelist als Liste der Dateien zu einem Programmierprojekt benutzen. Um diese zu übersetzen, könnte der Befehl

cc -o projekt `cat filelist`

abgesetzt werden. Eine Sicherung der Quelltexte könnte dann per

cp `cat filelist` /usr/projekt/backup

Alternativschreibweise in Klammern mit Dollar vorn

erfolgen. Leider sind die Backquotes im Ausdruck kaum von einem Apostroph zu unterscheiden. Beide haben aber unter UNIX eine deutlich unterschiedliche Bedeutung. Als Alternativschreibweise bieten die meisten Shells an, den in Backquotes stehenden Ausdruck einzuklammern und ein Dollarzeichen voranzustellen. Damit sind die beiden untenstehenden Ausdrücke gleichbedeutend.

ls -l `cat filelist`
ls -l $(cat filelist)

Diese Seite basiert auf Inhalten aus dem Buch Arnold Willemer: Wie werde ich UNIX-Guru.