So verwenden Sie den xargs-Befehl unter Linux

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.