Warum ist xargs notwendig?


25

Angenommen, ich möchte alle Dateien in einem Verzeichnis mit Ausnahme der Datei "notes.txt" entfernen. Ich würde das mit der Pipeline machen ls | grep -v "notes.txt" | xargs rm. Warum brauche ich xargs, wenn der Ausgang der zweiten Pipe der Eingang ist, den rm verwenden soll?

Zu Vergleichszwecken echo "#include <knowledge.h>" | cat > foo.cfügt die Pipeline den wiedergegebenen Text ohne die Verwendung von xargs in die Datei ein. Was ist der Unterschied zwischen diesen beiden Pipelines?


3
Sie sollten nicht verwenden ls | grep -v "notes.txt" | xargs rm, um alles zu entfernen, es sei denn notes.txt, Sie analysieren niemals die lsAusgabe . Ihr Befehl würde abbrechen, wenn eine einzelne Datei beispielsweise ein Leerzeichen enthält. Der sicherere Weg wäre rm !(notes.txt)in Bash (mit shopt -s extglobSatz) oder rm ^notes.txtin Zsh (mit EXTENDED_GLOB) usw.
Slhck

Um Leerzeichen zu vermeiden, können Sie find . -maxdepth 1 -mindepth 1 -print0 | xargs -0stattdessen ls | xargs
Folgendes

Antworten:


35

Sie verwechseln zwei sehr unterschiedliche Arten von Eingaben: STDIN und Argumente. Argumente sind eine Liste von Zeichenfolgen, die dem Befehl beim Start bereitgestellt werden, in der Regel durch Angabe nach dem Befehlsnamen (z . B. echo these are some argumentsoder rm file1 file2). STDIN hingegen ist ein Strom von Bytes (manchmal Text, manchmal nicht), den der Befehl (optional) nach dem Start lesen kann. Hier sind einige Beispiele (Anmerkung, catdie entweder Argumente oder STDIN annehmen kann, aber verschiedene Dinge damit macht):

echo file1 file2 | cat    # Prints "file1 file2", since that's the stream of
                          # bytes that echo passed to cat's STDIN
cat file1 file2    # Prints the CONTENTS of file1 and file2
echo file1 file2 | rm    # Prints an error message, since rm expects arguments
                         # and doesn't read from STDIN

xargs Man kann sich vorstellen, wie man eine Eingabe im STDIN-Stil in Argumente umwandelt:

echo file1 file2 | cat    # Prints "file1 file2"
echo file1 file2 | xargs cat    # Prints the CONTENTS of file1 and file2

echo Tatsächlich macht es mehr oder weniger das Gegenteil: Es konvertiert seine Argumente in STDOUT (das an die STDIN eines anderen Befehls weitergeleitet werden kann):

echo file1 file2 | echo    # Prints a blank line, since echo doesn't read from STDIN
echo file1 file2 | xargs echo    # Prints "file1 file2" -- the first echo turns
                                 # them from arguments into STDOUT, xargs turns
                                 # them back into arguments, and the second echo
                                 # turns them back into STDOUT
echo file1 file2 | xargs echo | xargs echo | xargs echo | xargs echo    # Similar,
                                 # except that it converts back and forth between
                                 # args and STDOUT several times before finally
                                 # printing "file1 file2" to STDOUT.

9

catnimmt Eingaben von STDINund rmnicht. Für solche Befehle müssen Sie zeilenweise xargsiterieren STDINund die Befehle mit Befehlszeilenparametern ausführen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.