Wie man xargs verwendet, um Befehlszeilen aus Standardeingaben zu erstellen
Selbst die einfachste Installation einer Linux-Distribution enthält eine Reihe wirklich nützlicher Dienstprogramme: "xargs" ist zweifellos eines davon. Durch die Verwendung von xargs können wir Befehlszeilen erstellen und ausführen, indem wir Elemente aus der Standardeingabe als Argumente eines Befehls verwenden. Dies ist besonders nützlich, wenn es sich um Programme handelt, die die Standardeingabe nicht direkt lesen.
In diesem Artikel erfahren Sie, wie Sie das Dienstprogramm xargs auf den am häufigsten verwendeten Linux-Distributionen installieren und wie Sie es zum Erstellen und Ausführen von Befehlszeilen verwenden.
In diesem Tutorial lernen Sie:
- So installieren Sie xargs auf den am häufigsten verwendeten Linux-Distributionen
- So verwenden Sie xargs zum Erstellen und Ausführen von Befehlszeilen
- Umgang mit Leerzeichen in Dateinamen
- Wie man xargs dazu bringt, vor dem Ausführen eines Befehls nach Bestätigung zu fragen
- Ausführen mehrerer Befehle für jedes Element
Installation
Das Dienstprogramm xargs wird normalerweise im Paket findutils verteilt, das ein weiteres sehr nützliches Befehlszeilenwerkzeug enthält: "find ". Das Paket ist Teil selbst der minimalsten Installation praktisch jeder Linux-Distribution, daher sollten wir es nicht explizit installieren müssen. Wenn es jedoch aus irgendeinem seltsamen Grund in unserem System fehlt, können wir es mit unserem bevorzugten Distributionspaket-Manager zurückziehen.
Auf Debian und Debian-basierten Distributionen können wir zum Beispiel apt verwenden:
sudo apt install findutilsAuf Fedora und anderen Distributionen der Red Hat-Familie können wir stattdessen dnf verwenden:
sudo dnf install findutilsDas Paket ist auch im Archilinux "Core " Repository verfügbar und kann daher mit pacman installiert werden:
sudo pacman -S findutilsSchauen wir uns an, wie wir xargs verwenden können, um Befehlszeilen zu erstellen und auszuführen.
Verwenden von xargs zum Erstellen von Befehlszeilen
Was genau macht das Dienstprogramm xargs? Xargs verwendet Elemente, die an die Standardeingabe übergeben werden, typischerweise unter Verwendung eines Pipe-Umleitungsoperators, als zusätzliche Argumente eines Befehls, den wir zusammen mit einigen optionalen Anfangsargumenten angeben können. Die xargs-Syntax ist ziemlich einfach zu verstehen:
xargs [options] [command [initial-arguments]]Sehen wir uns einige Beispiele aus der Praxis für die Verwendung von xargs an.
Beispiel 1: Suchen von Dateien mit einer bestimmten Erweiterung, die eine Zeichenfolge enthält
Ein typischer Anwendungsfall von xargs ist, wenn wir in Dateien mit einer bestimmten Erweiterung nach einem String suchen müssen. Kürzlich wollte ich zum Beispiel ein Wordpress-Theme ändern, also musste ich herausfinden, in welcher PHP-Template-Datei sich das Code-Snippet befand, das ich ändern wollte. So habe ich xargs verwendet, um die Aufgabe zu erfüllen:
find theme -type f -name "*.php" | xargs grep -i "text-to-search"Schauen wir uns an, was dieser Befehl bewirkt. Zuerst haben wir find verwendet, um rekursiv im Theme-Verzeichnis zu suchen, und wir haben das Dienstprogramm angewiesen, nach regulären Dateien (-type f) zu suchen, deren Name auf ".php" endet (-name "*.php"), dann haben wir die Standardausgabe des Befehls an xargs weitergeleitet, so dass die Dateien, die den obigen Creteria entsprechen, als Argumente an den Befehl grep übergeben wurden.
An dieser Stelle denken Sie vielleicht: "Das Suchprogramm hat selbst die Option -exec, die einen bestimmten Befehl mit den Dateien ausführt, die der Suche als Argumente entsprechen, warum sollte ich xargs verwenden? ”. Die Antwort lautet: "weil xargs schneller ist". Werfen wir einen Blick auf dieses Beispiel. Angenommen, wir möchten alle ".txt"-Dateien im Verzeichnis ~/.config finden, die die Zeichenkette "wizard" enthalten. Wir verwenden die Zeit, um eine Zeitstatistik für die Befehlsausführung zu erhalten. Zuerst verwenden wir -exec:
time find ~/.config -type f -name "*.txt" -exec grep -i "wizard" {} \;Hier sind die Ergebnisse:
real 0m0.031s
user 0m0.010s
sys 0m0.020s
Versuchen wir es nun mit xargs:
time find ~/.config -type f -name "*.txt" | xargs grep -i "wizard"Diesmal erhalten wir folgende Statistiken:
real 0m0.015s
user 0m0.006s
sys 0m0.010s
Obwohl die Zeit nicht als richtiges Benchmark-Tool angesehen werden kann, insbesondere für kurzlaufende Befehle, gibt sie uns eine allgemeine Vorstellung davon, welcher Befehl schneller ist. Die Lücke zwischen den beiden Befehlen wird noch größer, wenn in einer größeren Menge von Dateien gesucht wird.
Beispiel 2: Erstellen eines Tarball-Archivs mit möglicherweise nicht vorhandenen Dateien
Hier ist ein weiterer Fall, in dem xargs nützlich sein könnte. Angenommen, wir möchten einen Tarball erstellen, der bestimmte Dateien enthält, die jedoch möglicherweise nicht existieren. Wenn wir versuchen, eine nicht vorhandene Datei in einen Tarball aufzunehmen, wird tar mit dem Status "Fehler" beendet:
tar -cpf archive.tar ~/nonexistingfile ~/.bashrc ~/.bash_profile
tar: Removing leading `/' from member names
tar: /home/doc/nonexistingfile: Cannot stat: No such file or directory
tar: Removing leading `/' from hard link targets
tar: Exiting with failure status due to previous errors
Eine mögliche Lösung besteht darin, tar anzuweisen, Lesefehler zu ignorieren, indem die Option --ignore-failed-read verwendet wird. Fehler zu ignorieren ist jedoch selten eine gute Idee. Eine bessere Lösung ist es, mit "Finden" nach den Dateien zu suchen, die wir in das Archiv legen möchten:
find ~ -maxdepth 1 -type f \( -name .bashrc -o -name .bash_profile -o -name nonexistingfile \) | xargs tar -cpf archive.tarIm obigen Beispiel habe ich angenommen, dass sich die Dateien alle direkt im Home-Verzeichnis befinden, daher habe ich die Option -maxdepth 1 verwendet, die die rekursive Suche tatsächlich deaktiviert. Ich habe auch den -type f-Filter verwendet, dann habe ich mehrere -name-Filter (einen für jede Datei) eingefügt, getrennt durch den -o-Operator, der als logisches ODER funktioniert.
Das Dienstprogramm "find" setzt einen impliziten logischen UND-Operator (-a) zwischen die angegebenen Tests, der eine höhere Priorität als OR hat. Aus diesem Grund haben wir die "name"-Tests in Klammern gruppiert (maskiert, um zu vermeiden, dass die Shell sie als Sonderzeichen interpretiert). Wäre dies nicht der Fall, hätte der Ausdruck wie folgt ausgesehen:
find ~ -maxdepth 1 -type f -a -name .bashrc -o -name .bash_profile -o -name nonexistingfileIm Klartext hätte dies bedeutet: "Finde eine reguläre Datei mit dem Namen ".bashrc" oder eine beliebige Art von Datei mit dem Namen ".bash_profile" oder eine beliebige Art von Datei mit dem Namen "nonexistingfile" im Home-Verzeichnis, ohne in Unterverzeichnisse abzusteigen.
Bei dieser Strategie wird eine Datei, die nicht existiert, nicht in die Liste der zu archivierenden Dateien aufgenommen.
Umgang mit Leerzeichen in Dateinamen
Es gibt eine Sache, die wir in den vorherigen Beispielen nicht berücksichtigt haben: Dateien, deren Name Leerzeichen enthält. xargs verwendet standardmäßig ein Leerzeichen als Trennzeichen für Elemente, daher wird es verwirrend sein, wenn eine Datei ein Leerzeichen als Teil ihres Namens enthält. Hier ist ein Beispiel. Angenommen, es gibt ein Verzeichnis, das drei Dateien enthält, von denen eine ein Leerzeichen als Teil ihres Namens enthält:
test
├── file1.txt
├── file2.txt
└── file 3.txt
Nehmen wir nun an, wir möchten in einer dieser Dateien nach einer Zeichenfolge suchen, wie wir es in den vorherigen Beispielen getan haben:
find test -type f | xargs grep -i "content"Wie erwartet schlägt der Befehl fehl:
grep: test/file: No such file or directory
grep: 3.txt: No such file or directory
Sehen Sie, was passiert ist? Da "Datei 3.txt" ein Leerzeichen im Namen hat und xargs ein Leerzeichen als Trennzeichen verwendet, wurden "Datei" und "3.txt" als zwei separate Elemente betrachtet! Wir können dieses Problem lösen, indem wir das Zeichen ändern, das xargs als Trennzeichen verwendet.
Wenn wir find und xargs kombinieren, können wir einfach die frühere Option -print0 verwenden: Dies bewirkt, dass auf jedes gefundene Element ein Nullzeichen folgt (Standard ist ein Zeilenumbruch). Auf der xargs-Seite können wir stattdessen die Option --null (oder -0) übergeben, die das Dienstprogramm anweist, ein Nullzeichen als Elementtrennzeichen zu verwenden und Anführungszeichen, umgekehrte Schrägstriche und das Ende von Dateizeichenfolgen buchstäblich zu berücksichtigen:
find test -type f -print0 | xargs --null grep -i "content"Als Alternative können wir die Option xargs -d verwenden, mit der wir angeben können, welches Zeichen wir als Trennzeichen verwenden möchten.
Xargs vor dem Ausführen eines Befehls um Bestätigung bitten lassen
In bestimmten Fällen möchten wir den Befehl, der von xargs ausgeführt wird, möglicherweise noch einmal überprüfen. In diesen Fällen können wir die Option -p oder --interactive verwenden. Wenden wir es auf das vorherige Beispiel an:
find test -type f -print0 | xargs --interactive --null grep -i "content"Hier ist das Ergebnis:
grep -i content test/file1.txt test/file2.txt 'test/file 3.txt'?...Der Befehl wird erst nach einer bestätigenden Antwort (mit y oder y) ausgeführt. Wenn wir nur möchten, dass der Befehl in der Standardausgabe ausgegeben wird, bevor er tatsächlich ausgeführt wird, können wir stattdessen die Option -t oder --verbose verwenden:
find test -type f -print0 | xargs --verbose --null grep -i "content"
grep -i content test/file1.txt test/file2.txt 'test/file 3.txt'
test/file 3.txt:contentAusführen mehrerer Befehle für jedes Element
Eine interessante Option, die wir mit xargs verwenden können, ist -I, mit der wir eine Art "Vorlage" erstellen können. Als Argument wird ein "Platzhalter" verwendet: Jedes Vorkommen des Platzhalters wird zur Laufzeit durch Elemente ersetzt, die aus der Standardeingabe gelesen werden. Nehmen wir als triviales Beispiel an, wir möchten den Benutzer benachrichtigen, dass wir nach einer Zeichenkette in einer Datei suchen, bevor wir den Befehl grep tatsächlich verwenden. Wir würden laufen:
find test -type f | xargs -I % /bin/sh -c 'echo "searching in %"; grep -i "content" "%"'Wenn die Option -I verwendet wird, wird das Zeichen "Zeilenumbruch" (\n) als Trennzeichen verwendet, daher müssen wir, wie Sie sehen können, --null nicht verwenden, und wir können einfach den Platzhalter % in Anführungszeichen setzen.
Schlüsse
In diesem Tutorial haben wir gelernt, wie man das Dienstprogramm xargs verwendet, um Befehlszeilen aus der Standardeingabe zu erstellen und auszuführen. Das Dienstprogramm xargs wird im Paket "findutils" ausgeliefert, zusammen mit einem anderen sehr nützlichen Programm: "find" und wird oft in Verbindung damit verwendet, wie wir in den Beispielen gesehen haben.
