In den ersten zwei Teilen der Shell-Einführung [1,2] haben wir Sie mit den Grundlagen der Shell vertraut gemacht. Jetzt stellen wir einige Spezialtools vor, mit denen die Shell besonders leistungsfähig wird – darunter “xargs”.
In der letzten Ausgabe haben wir Ihnen am Ende des Guru-Trainings einen Befehl vorgestellt, mit dem Sie mehrere mit find gefundene PDF-Dateien gleichzeitig im Adobe Reader öffnen können – mit dem Versprechen, das genauer zu erklären. Der Befehl war:
find /tmp/ -name '*.pdf' -print0 | xargs -0 acroread
Er besteht aus zwei Kommandos, die über eine so genannte Pipe miteinander verbunden sind:
- Das erste Kommando lautet
find /tmp/ -name '*.pdf' -print0und findet alle Dateien mit Endung .pdf, die im temporären Ordner /tmp/ oder einem seiner Unterverzeichnisse liegen. Die zusätzliche Option -print0 ist für den Zweck des anschließenden Adobe-Reader-Starts wichtig, denn Sie bewirkt, dassfindin der Ausgabe nicht Leerzeichen oder Zeilenumbrüche, sondern ein spezielles Sonderzeichen zwischen die Dateinamen schreibt. Das hat den Vorteil, dass der gesamte Befehl auch dann funktioniert, wenn sich in einigen der Dateinamen Leerzeichen befinden. - Über das Pipe-Zeichen | wird die Ausgabe des ersten Kommandos (eine Liste von Dateinamen) zur Eingabe für das zweite Kommando. Es heißt
xargs -0 acroread. Das Toolxargsist besonders praktisch: Es wandelt Informationen aus der Standardeingabe in Argumente um. Die Wirkung können Sie leicht ausprobieren, indem Sie den Befehlls / | xargs echoeingeben –ls /gibt den Inhalt des Wurzelverzeichnisses aus, undxargsmacht aus dieser Ausgabe Argumente für den Befehlecho, der einfach seine Argumente ausgibt (siehe Kasten Ausgabe als Argumente). Die Option-0(das ist eine Null, nicht der Großbuchstabe O) teiltxargsmit, dass es nicht normale Leerzeichen als Trenner für die verschiedenen Argumente interpretieren soll, sondern das Sonderzeichen, dasfindüber die Option-print0als Trenner eingefügt hat.
Die Regel ist: Wenn Sie find und xargs auf diese Weise kombinieren, müssen Sie entweder find mit der Option -print0 und xargs mit der Option -0 verwenden oder bei beiden Kommandos auf die Optionen verzichten – anderenfalls passen Ausgabe und Eingabe nicht zusammen, und xargs “versteht” Sie nicht.
Ausgabe als Argumente
Das folgende Kommando gibt den Inhalt des Wurzelverzeichnisses aus, setzt aber noch die Worte “Inhalt Wurzelverzeichnis:” vor die Ausgabe.
$ ls / | xargs echo "Inhalt Wurzelverzeichnis:" Inhalt Wurzelverzeichnis: bin boot dev etc home lib lost+found media mnt opt proc root sbin srv sys tmp usr var
Das funktioniert in drei Schritten:
- Das Kommando
ls /listet den Inhalt des Wurzelverzeichnisses auf, gibt also z. B.bin boot dev etc home lib lost+found media mnt opt proc root sbin srv sys tmp usr varaus. Wenn Sie den Befehl alleine aufrufen, erscheinen diese Namen direkt in der Shell. - Über das Pipe-Zeichen reichen Sie die Ausgabe als Standardeingabe an das folgende Kommando weiter.
xargs echo "Inhalt Wurzelverzeichnis:"liest zunächst von der Standardeingabe. Es erhält dort die schon mehrfach gezeigte Liste von Verzeichnisnamen. Es baut dann ein neues Kommando zusammen, das sich ausecho "Inhalt Wurzelverzeichnis:"und der neuen Argumentliste zusammensetzt, so entsteht der Befehlecho "Inhalt Wurzelverzeichnis:" bin boot dev etc home lib lost+found media mnt opt proc root sbin srv sys tmp usr var. Diesen Befehl führtxargsdann aus.- Das Kommando
echoweiß nichts von dem Umweg, auf dem es seine Argumente erhalten hat; es “sieht” einfach nur, dass es mit den Argumenten"Inhalt Wurzelverzeichnis:" bin boot dev etc home lib lost+found media mnt opt proc root sbin srv sys tmp usr varaufgerufen wurde, und gibt diesen Text aus.
Für Sammler: Umleitungen
Wollen Sie die Ausgabe eines Programms nicht (nur) im Terminalfenster sehen, sondern dauerhaft archivieren oder etwa für den Versand als E-Mail-Anhang in einer Datei sichern, nutzen Sie ein praktisches Feature der Shell: die Ausgabeumleitung. Dazu setzen Sie ganz am Schluss hinter das Kommando ein Größerzeichen (>) und einen Dateinamen: Die Ausgabe des Befehls landet in der Datei.
Jeder solche Aufruf mit > Dateiname löscht zunächst einen eventuell vorhandenen Inhalt der Datei und schreibt dann die Ausgabe hinein – so können Sie immer nur eine einzige Programmausgabe sichern. Soll eine Datei die Ergebnisse mehrerer Befehle enthalten, verwenden Sie statt > ein doppeltes Größer-Zeichen (>>): Dann hängt die Shell die Ausgabe an die Zieldatei an, ohne diese vorher zu leeren.
Beide Varianten können Sie auch kombinieren: Um etwa die Ausgaben von befehl1, befehl2 und befehl3 in der Datei /tmp/ausgaben.logzu protokollieren, geben Sie die Kommandos
befehl1 > /tmp/ausgaben.log befehl2 >> /tmp/ausgaben.log befehl3 >> /tmp/ausgaben.log
ein. Die erste Zeile sorgt über das einfache >-Zeichen zunächst dafür, dass die Zieldatei leer ist, bevor erste Informationen darin landen. Die zweiten und dritten Zeilen hängen dann die Ausgaben an die Datei an.
Beachten Sie, dass > und >> nur “normale” Ausgaben eines Befehls erfassen. Es gibt auch spezielle Fehlerausgaben, die aus Linux-Sicht über einen anderen “Kanal” laufen, die so genannte Standardfehlerausgabe (stderr). Entsprechend heißt die normale Ausgabe Standardausgabe (stdout). Erzeugt ein Programm neben den regulären Ausgaben auch Fehlermeldungen, bleiben diese weiterhin im Terminalfenster sichtbar und stehen nicht in der Zieldatei. Um auch die Fehler in der Datei zu protokollieren, passen Sie die Befehlszeile an und stellen vor das > bzw. >> ein kaufmännisches Und (&), insgesamt also: &> bzw. &>>. Liegt im aktuellen Arbeitsverzeichnis z. B. eine Datei mozilla.ps, aber keine Datei namens mozzzllla.ps, dann erzeugt der Befehl
ls -l mozilla.ps mozzzllla.ps &> /tmp/test.log
sowohl eine reguläre Ausgabe (Informationen über die Datei mozilla.ps) als auch eine Fehlerausgabe (über das Fehlen der anderen Datei). Beide Ausgaben landen nun dank der Umleitung mit &> in der Datei test.log, was Sie mit cat schnell überprüfen können:
esser@netbookhg:~$ cat /tmp/test.log ls: Zugriff auf mozzzllla.ps nicht möglich: No such file or directory -rw-r--r-- 1 esser esser 1482262 2010-02-07 00:22 mozilla.ps
Probieren Sie auch die Variante ohne das kaufmännische Und aus und vergleichen Sie die Ergebnisse.
Suchen und Ersetzen
Um in einer Datei konsequent das Wort “Apfel” durch “Birne” zu ersetzen, können Sie diese in einem Editor öffnen und dessen Ersetzenfunktion verwenden. Es geht aber auch auf der Shell, wenn Sie das Kommando sed verwenden. Dessen Syntax ist ein wenig gewöhnungsbedürftig, für einfache Aufgaben aber schnell gemeistert: Heißt Ihre Datei etwa test.txt, können Sie mit
sed -e s/Apfel/Birne/g test.txt > test2.txt
die Ersetzungen vornehmen. Die überarbeitete (Birnen-)Fassung landet dabei in der Datei test2.txt. Zur Erläuterung:
- Die Option
-eleitet einen Ausdruck (englisch: expression) ein, damit sagen Siesed, was zu tun ist. - Der folgende Text
s/Apfel/Birne/gist ein solcher Ausdruck. Er beginnt mit einem Kommando (s, substitute = ersetzen), nach einem Schrägstrich folgt der zu ersetzende Begriff (Apfel), nach einem weiteren Schrägstrich der einzusetzende Text (Birne) und nach dem letzten Schrägstrich noch eine Option (g, global), welche dafür sorgt, dasssedauch mehrere Treffer in einer einzelnen Zeile ersetzt. - Es folgt als weiteres Argument der Name der Datei (
test.txt), - und über die Umleitung
> test2.txtschreiben Sie das Ergebnis der Ersetzung in die Datei test2.txt.
Dabei achtet sed genau auf die Unterschiede zwischen Groß- und Kleinschreibung – ein Vorkommen von “apfel” oder “aPFEL” würde das Kommando hier also ignorieren. Wortgrenzen spielen andererseits keine Rolle, aus “Apfelkompott” wird das grammatikalisch fehlerhafte “Birnekompott”, weil eben in “Apfelkompott” der gesuchte Begriff “Apfel” vorkommt.
Um auch andere Schreibweisen (“apfel”, “aPFEL” etc.) zu ersetzen, können Sie die zusätzliche Option i (ignore case, Groß-/Kleinschreibung ignorieren) verwenden, die Sie hinter der Option g ergänzen – der Befehl wird damit
sed -e s/Apfel/Birne/gi test.txt > test2.txt
Abbildung 1 zeigt eine Beispieldatei und das Produkt des obigen Kommandos, wobei die jeweiligen Vorkommen von “Apfel” oder “Birne” durch einen Aufruf von grep farblich hervorgehoben sind. Dort sehen Sie, dass sed nun unabhängig von Groß- und Kleinschreibung alle Äpfel im Text findet. Ersetzt wird dabei aber immer durch “Birne” in genau dieser Schreibweise – sed hätte keine Möglichkeit zu erahnen, dass Sie etwa “aPFEl” durch “bIRNe” ersetzen möchten.
Schnell sortiert
Die Ausgaben aller Shell-Kommandos können Sie mit dem Sortierprogramm sort in eine richtige Reihenfolge bringen. Dabei ist sort sehr mächtig und kommt auch mit der Aufgabe zurecht, komplexere tabellarische Ausgaben nach bestimmten Spalten zu sortieren. Ein einfacher sort-Aufruf sortiert alphanumerisch, also nach dem Alphabet, während sort -n nach Zahlen sortiert, also z. B. “1”, “2” und “11” in die richtige Reihenfolge bringt, während bei alphabetischer Sortierung die “11” zwischen “1” und “2” landet. Abbildung 2 zeigt ein Beispiel dafür.

Abbildung 2: Zeilen, die mit Zahlen beginnen, können Sie alphanumerisch (“sort”) oder numerisch (“sort -n”) sortieren.
Sie können sort direkt mit dem Namen einer zu sortierenden Datei als Argument aufrufen oder das Tool wieder in einer Pipeline einsetzen. So filten Sie beispielsweise aus einer großen Datei zunächst mit grep die interessanten Zeilen heraus und bringen diese anschließend mit sort in die richtige Reihenfolge:
$ grep München adressdatei.txt | sort Amussen, Joseph, München, Hauptstraße 3 Meier, Martina, München, Isarweg 9 Roth, Karla, München, Postchaussee 17 Zülow, Anton, München, Nordpark 1
Sie könnten auch den umgekehrten Weg gehen (erst sortieren, dann filtern), aber das vergrößert die Antwortzeit, denn etwas zu sortieren, ist eine anspruchsvollere Aufgabe als, Dinge herausfiltern.
Tauchen in der Ausgabe mehrere identische Zeilen auf, können Sie sort dazu auffordern, diese “Doppler” zu entfernen. Dazu verwenden Sie die Option -u (unique, einmalig). Das funktioniert auch, wenn eine Datei bereits sortiert ist (und eventuell Doppler enthält) – dann ist es aber sinnvoller, statt sort das kleine Tool uniq zu verwenden, das von einer bereits sortierten Eingabe ausgeht und einfach alle doppelt oder öfter auftretenden Zeilen streicht.
Mehr Power als man denkt
Die Shell ist ein echtes Powertool: In unserer dreiteiligen Einführung haben wir Sie mit den Grundlagen vertraut gemacht und einige nützliche Tools vorgestellt. In jeder EasyLinux-Ausgabe finden Sie in den Shell-Tipps (in diesem Heft auf Seite 102) weitere Hinweise dazu, was auf der Shell alles möglich ist. Eine zusätzliche Fundgrube bietet das Archiv unserer Schwesterzeitschrift LinuxUser [3], dort gibt es vor allem in den älteren Artikeln der Rubrik “Zu Befehl” viele interessante Shell-Programm-Vorstellungen.
Haben Sie besondere Erwartungen an die Arbeit mit der Shell? Gibt es Aufgaben, die Sie gerne auf der Kommandozeile lösen würden, aber Sie kennen nicht den richtigen Weg? Dann schreiben Sie an die Redaktionsadresse – wir greifen Ihre Themenvorschläge gerne auf.
Infos
[1] Shell-Einführung, Teil 1: Hans-Georg Eßer, “Im Anfang war der Prompt”, EasyLinux 01/2010, S. 124 ff., https://www.linux-community.de/artikel/20197
[2] Shell-Einführung, Teil 2: Hans-Georg Eßer, “Hilfreiche Spezialisten”, EasyLinux 02/2010, S. 124 ff., https://www.linux-community.de/artikel/20420
[3] LinuxUser: http://www.linux-user.de/


