[[:tux|{{ :linux.png?40|}}]]
===== xargs: Syntax und Beispiele ====
Häufig findet man im Diskussions-Forum Anfragen, die immer auf ein und dasselbe Problem herauslaufen: Man möchte viele Dateien (manchmal über den ganzen Verzeichnisbaum verteilt) gleichartig behandeln. Ob die Dateien zB nun gelöscht (rm), der Eigentümer oder die Zugriffsrechte gewechselt werden (chown; chmod) oder die Dateien verschoben werden sollen (mv), ist dabei eigentlich egal. Zumeist wird von der aktiven Forums-Gemeinde die naheliegendste Lösung genannt: Das **//[[:tux:find|-> find-Kommando]]//**. Neben der flexiblen Suche ist die interessanteste Fähigkeit von find die Ausführung eines Kommandos auf jede der gefundenen Dateien. Die zuständige Option heißt -exec. Dahinter wird ein Befehl gesetzt, der mit einem Semikolon abgeschlossen wird. Letzteres muss durch einen Backslash gegen die Interpretation durch die Shell geschützt werden. Die Shell würde das Semikolon als Trennzeichen zwischen zwei Befehlen interpretieren, die nacheinander ausgeführt werden. Vergißt man den Backslash, würde die Shell das Semikolon selbst interpretieren und nicht an find weiterreichen. Der Bezug auf die gefundene Datei wird im Befehl durch ein Paar geschweifter Klammern repräsentiert. Man stelle sich nun vor, alle Dateien eines in Ungnade gefallenen Users sollen gelöscht werden:
$ find / -user foobar -exec rm {} \;
Und an dieser Lösung ist auch nichts Falsches. Sie funktioniert einwandfrei und ist in diesem speziellen Fall auch schnell eingetippt. Das Problem an dieser Lösung taucht auf, wenn man sehr viele Dateien bearbeiten muss: Pro Datei wird ein eigenes rm-Kommando abgesetzt. Findet find nun 2000 Dateien des Ex-Users foobar, werden (hintereinander) 2000 Prozesse gestartet, die jeweils nur eine Datei löschen. Auch auf moderneren Rechnern ist das eine nicht zu unterschätzende Last. Nun muss man sich nur noch daran erinnern, dass rm ja mehrere Dateien auf einmal löschen kann. Also wäre ein einzelnes rm-Kommando mit 2000 Argumenten viel sinnvoller als anders herum.
Genau an dieser Stelle kommt xargs ins Spiel. Die man-Page zu xargs((http://unixhelp.ed.ac.uk/CGI/man-cgi?xargs)) verrrät uns, dass der Sinn und Zweck von xargs //"build and execute command lines from standard input"// ist, also das Erstellen und Ausführen von Kommandos (mit Hilfe der Daten) aus der Standard-Eingabe.
$ find / -user foobar -print | xargs rm
find listet alle Dateien des Users foobar auf und reicht sie über die Pipe an xargs weiter. xargs nimmt die Liste von der Standardeingabe und bastelt daraus und aus dem rm, was ihm als Argument übergeben wurde, ein rm-Kommando mit 2000 Argumenten. Ergebnis: 3 Prozesse anstelle von 2001 Prozessen in der ersten Variante, um 2000 Dateien zu löschen. Einen Haken allerdings hat dieser Befehl: find maskiert bei der Ausgabe evtl vorhandene Leerzeichen nicht mit einem Backslash. Man kann dem find-Kommando aber mitteilen, dass es gefundene Zeichenketten mit einem ASCII-NULL beenden soll (-print0) und xargs anweisen, es möge solche erwarten (-0)
$ find / -user foobar -print0 | xargs -0 rm
Ein weiteres Problem kann auftauchen, wenn man anstatt wie beim Beispiel rm, welches nur ein Argument erwartet, ein Kommando absetzen möchte, welches mehrere Argumente erwartet. zB das mv-Kommando erwartet als erstes Argument die/das zu verschiebende Datei/Verzeichnis und als zweites Argument das Zielverzeichnis. Man muss xargs nun sagen, an welcher Stelle die Argumentliste für das Kommando eingefügt werden soll. Dazu wird die Zeichenkette {} als Platzhalter verwendet.
$ find / -user foobar -print0 | xargs -0 mv {} /tmp/foobar
\\
**Verwandte Artikel:**
[[:tux:find|-> find: Syntax und Beispiele]]
[[:tux:chmod|-> chmod rekursiv auf Dateien und Verzeichnisse anwenden]]
\\
--- //pronto 2008/09/09 12:53//
{{keywords>linux osx mac syntax beispiele find}}