Müssen Sie in Linux einige Befehle verketten, aber einer davon akzeptiert keine Eingabe über eine Pipe? Das Dienstprogramm xargs
kann die Ausgabe eines Befehls entgegennehmen und diese als Argumente an einen anderen Befehl übergeben.
Jedes Standard-Linux-Werkzeug verfügt über drei Datenströme: den Standardeingabestrom (stdin), den Standardausgabestrom (stdout) und den Standardfehlerstrom (stderr).
Diese Ströme funktionieren mit Text. Wir übermitteln mit Text eine Eingabe (stdin) an einen Befehl, und die Antwort (stdout) wird ebenfalls als Text in das Terminalfenster geschrieben. Fehlermeldungen (stderr) werden ebenfalls als Text im Terminal angezeigt.
Eine der Stärken von Linux und Unix-ähnlichen Systemen ist die Fähigkeit, die stdout-Ausgabe eines Befehls in die stdin-Eingabe eines anderen Befehls umzuleiten. Der erste Befehl weiß nicht, dass seine Ausgabe nicht in ein Terminal geht, und der zweite Befehl weiß nicht, dass seine Eingabe nicht von einer Tastatur stammt.
Obwohl alle Linux-Befehle diese drei Standardströme haben, akzeptieren nicht alle die stdout eines anderen Befehls als Eingabe für ihre stdin. Das bedeutet, dass Sie keine Ausgaben an sie weiterleiten können.
xargs
ist ein Befehl, mit dem Ausführungspipelines mithilfe von Standarddatenströmen erstellt werden können. Mit xargs
können wir Befehle wie echo
, rm
und mkdir
dazu bringen, Standardeingaben als Argumente zu verarbeiten.
Der Befehl xargs
xargs
empfängt Eingaben über Pipes. Es kann auch Eingaben aus einer Datei entgegennehmen. xargs
verwendet diese Eingabe als Parameter für die Befehle, mit denen es verwendet werden soll. Wenn wir xargs
nicht explizit anweisen, einen bestimmten Befehl zu verwenden, wird standardmäßig echo
verwendet.
Damit können wir demonstrieren, wie xargs
immer eine einzelne Ausgabezeile generiert, selbst bei mehrzeiliger Eingabe.
Wenn wir die Option -1
(eine Datei pro Zeile auflisten) mit ls
verwenden, erhalten wir eine einzelne Spalte mit Dateinamen.
ls -1 ./*.sh
Dies listet die Shell-Skriptdateien im aktuellen Verzeichnis auf.
Wie erwartet erhalten wir eine einzige Spalte. Was passiert, wenn wir die Ausgabe an xargs
weiterleiten?
ls -1 ./*.sh | xargs
Die Ausgabe wird als langer Textstrom in das Terminalfenster geschrieben.
Diese Fähigkeit ermöglicht es xargs
, Parameter an andere Befehle zu übergeben.
Verwendung von xargs
mit wc
Wir können xargs
verwenden, um wc
auf einfache Weise Wörter, Zeichen und Zeilen in mehreren Dateien zählen zu lassen.
ls *.page | xargs wc
Folgendes geschieht:
ls
listet die *.page
-Dateien auf und übergibt die Liste an xargs
.xargs
übergibt die Dateinamen an wc
.wc
behandelt die Dateinamen, als hätte es sie als Befehlszeilenparameter erhalten.
Die Statistiken für jede Datei werden zusammen mit einer Gesamtsumme angezeigt.
Verwendung von xargs
mit Bestätigung
Wir können die Option -p
(interaktiv) verwenden, damit xargs
uns zur Bestätigung auffordert, bevor es fortfährt.
Wenn wir eine Zeichenfolge von Dateinamen über xargs
an touch
übergeben, wird touch
die Dateien erstellen.
echo 'one two three' | xargs -p touch
Der auszuführende Befehl wird angezeigt, und xargs
wartet auf unsere Antwort, indem wir „y“, „Y“, „n“ oder „N“ eingeben und die Eingabetaste drücken.
Wenn Sie nur die Eingabetaste drücken, wird dies als „n“ interpretiert. Der Befehl wird nur ausgeführt, wenn Sie „y“ oder „Y“ eingeben.
Wir haben „y“ gedrückt und die Eingabetaste gedrückt. Wir können ls
verwenden, um zu überprüfen, ob die Dateien erstellt wurden.
ls one two three
Verwendung von xargs
mit mehreren Befehlen
Wir können mehrere Befehle mit xargs
verwenden, indem wir die Option -I
(Initialargumente) verwenden.
Diese Option definiert einen „Ersetzungsstring“. Überall dort, wo das Token für den Ersetzungsstring in der Befehlszeile erscheint, werden die an xargs
gelieferten Werte eingefügt.
Verwenden wir den Befehl tree
, um die Unterverzeichnisse des aktuellen Verzeichnisses anzuzeigen. Die Option -d
(Verzeichnis) bewirkt, dass tree
Dateien ignoriert und nur über Verzeichnisse berichtet.
tree -d
Es gibt ein einzelnes Unterverzeichnis namens „images“.
In einer Datei namens „directories.txt“ haben wir die Namen einiger Verzeichnisse, die wir erstellen möchten. Mit cat
können wir uns den Inhalt anzeigen lassen.
cat directories.txt
Diese Datei werden wir als Eingabe für xargs
verwenden. Der Befehl, den wir ausführen werden, lautet:
cat directories.txt | xargs -I % sh -c 'echo %; mkdir %'
Dieser Befehl setzt sich wie folgt zusammen:
cat directory.txt |
: Leitet den Inhalt der Datei directories.txt
(alle neuen Verzeichnisnamen) an xargs
weiter.xargs -I %
: Definiert einen „Ersetzungsstring“ mit dem Token „%“.sh -c
: Startet eine neue Subshell. Das -c
(Befehl) weist die Shell an, Befehle von der Befehlszeile zu lesen.'echo %; mkdir %'
: Jedes „%“-Token wird durch die Verzeichnisnamen ersetzt, die von xargs
übergeben werden. Der echo
-Befehl gibt den Verzeichnisnamen aus; der mkdir
-Befehl erstellt das Verzeichnis.
Die Verzeichnisse werden nacheinander ausgegeben.
Wir können tree
erneut verwenden, um zu überprüfen, ob die Verzeichnisse erstellt wurden.
tree -d
Kopieren von Dateien an mehrere Speicherorte
Wir können xargs
verwenden, um Dateien mit einem einzigen Befehl an mehrere Speicherorte zu kopieren.
Wir leiten die Namen von zwei Verzeichnissen als Eingabeparameter an xargs
. Wir weisen xargs
an, nur einen dieser Parameter gleichzeitig an den Befehl zu übergeben, mit dem es arbeitet.
In diesem Fall ist der Befehl cp
. Der Effekt ist also, cp
zweimal aufzurufen, jedes Mal mit einem der beiden Verzeichnisse als Befehlszeilenparameter. Der Parameter xargs
, der dies ermöglicht, ist die Option -n
(max. Anzahl). Wir stellen dies auf eins.
Wir verwenden auch die Option -v
(verbose) mit cp
, damit diese über die durchgeführten Aktionen informiert.
echo ~/Backups/ ~/Documents/page-files/ | xargs -n 1 cp -v ./*.page
Die Dateien werden nacheinander in die beiden Verzeichnisse kopiert. cp
meldet jede Dateikopieraktion, sodass wir die Ausführung verfolgen können.
Löschen von Dateien in verschachtelten Verzeichnissen
Wenn Dateinamen Leerzeichen und Sonderzeichen, wie z. B. Zeilenumbrüche, enthalten, kann xargs
diese nicht richtig interpretieren. Wir können dieses Problem lösen, indem wir die Option -0
(Null-Terminator) verwenden. Dies weist xargs
an, das Nullzeichen als letztes Trennzeichen für Dateinamen zu verwenden.
In diesem Beispiel verwenden wir find
. find
hat eine eigene Option für den Umgang mit Leerzeichen und Sonderzeichen in Dateinamen. Dies ist die Option -print0
(vollständiger Name, Nullzeichen).
find . -name "*.png" -type f -print0 | xargs -0 rm -v -rf "{}"
Dieser Befehl setzt sich wie folgt zusammen:
find . -name "*.png"
: find
sucht im aktuellen Verzeichnis „.“ nach Objekten mit Namen, die mit „*.png“ übereinstimmen und Dateien sind (-type f
).-print0
: Namen werden mit einem Nullzeichen abgeschlossen, wobei Leerzeichen und Sonderzeichen berücksichtigt werden.xargs -0
: xargs
betrachtet Dateinamen ebenfalls als Null-terminiert, und Leerzeichen und Sonderzeichen verursachen keine Probleme.rm -v -rf "{}"
: rm
wird ausführlich berichten, was geschieht (-v
). Es wird rekursiv (-r
) und durchsucht verschachtelte Unterverzeichnisse und entfernt Dateien ohne Aufforderung (-f
). Das „{}“ wird durch jeden Dateinamen ersetzt.
Alle Unterverzeichnisse werden durchsucht, und die Dateien, die dem Suchmuster entsprechen, werden gelöscht.
Verschachtelte Verzeichnisse entfernen
Angenommen, wir möchten mehrere verschachtelte Unterverzeichnisse entfernen. tree
zeigt sie uns.
tree -d
find . -name "level_one" -type d -print0 | xargs -0 rm -v -rf "{}"
Dieser Befehl verwendet find
, um rekursiv im aktuellen Verzeichnis zu suchen. Das Suchziel ist ein Verzeichnis namens „level_one“. Die Verzeichnisnamen werden über xargs
an rm
übergeben.
Die einzigen wesentlichen Änderungen zwischen diesem Befehl und dem vorherigen Befehl sind, dass das Suchkriterium der Name des obersten Verzeichnisses ist und -type d
anweist, nach Verzeichnissen und nicht nach Dateien zu suchen.
Der Name jedes Verzeichnisses wird ausgegeben, wenn es entfernt wird. Wir können es mit tree
überprüfen:
tree -d
Alle verschachtelten Unterverzeichnisse werden gelöscht.
Löschen aller Dateien mit Ausnahme eines Dateityps
Wir können find
, xargs
und rm
verwenden, um alle Dateien außer einem Typ zu löschen, den wir behalten möchten. Es ist etwas unintuitiv, aber wir geben den Namen des Dateityps an, den wir behalten möchten, und nicht den Namen derer, die wir löschen möchten.
Die Option -not
weist find
an, die Namen der Dateien zurückzugeben, die nicht dem Suchmuster entsprechen. Wir verwenden die Option -I
(Initialargumente) erneut mit xargs
. Diesmal ist das Ersetzungsstring-Token, das wir definieren, „{}“. Dies verhält sich genauso wie das zuvor generierte Token zum Ersetzen des Strings, das zufällig ein „%“ war.
find . -type f -not -name "*.sh" -print0 | xargs -0 -I {} rm -v {}
Wir können mit ls
überprüfen. Die einzigen Dateien, die im Verzeichnis verbleiben, sind die, die dem Suchmuster „*.sh“ entsprechen.
ls -l
Erstellen einer Archivdatei mit xargs
Wir können find
verwenden, um nach Dateien zu suchen und diese über xargs
an tar
zu übergeben, um eine Archivdatei zu erstellen.
Wir suchen im aktuellen Verzeichnis. Das Suchmuster ist „*.page“, also suchen wir nach „.page“-Dateien.
find ./ -name "*.page" -type f -print0 | xargs -0 tar -cvzf page_files.tar.gz
Die Dateien werden während der Erstellung der Archivdatei wie erwartet aufgelistet.
Der Datenvermittler
Manchmal braucht man beim Stapeln etwas Unterstützung. xargs
überbrückt die Lücke zwischen Befehlen, die Informationen ausgeben können, und Befehlen, die nicht für die Verarbeitung dieser Informationen ausgelegt sind.
Sowohl xargs
als auch find
haben eine große Anzahl von Optionen. Es wird empfohlen, ihre Manpages zu lesen, um mehr zu erfahren.