Warum ist xargs notwendig?

5732
seewalker

Angenommen, ich möchte alle Dateien in einem Verzeichnis mit Ausnahme des Namens "notes.txt" entfernen. Ich würde tut dies mit der Pipeline ls | grep -v "notes.txt" | xargs rm. Warum brauche ich xargs, wenn die Ausgabe der zweiten Pipe die Eingabe ist, die rm verwenden soll?

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

19
Sie sollten `ls | nicht verwenden grep -v "notes.txt" | xargs rm`, um alles außer "notes.txt" zu entfernen, oder generell [nie "ls" -Ausgabe analysieren] (http://mywiki.wooledge.org/ParsingLs). Ihr Befehl würde fehlschlagen, wenn beispielsweise eine einzelne Datei ein Leerzeichen enthält. Der sicherere Weg wäre `rm! (Notes.txt)` in Bash (mit `shopt -s extglob`-Satz) oder` rm ^ notes.txt` in Zsh (mit `EXTENDED_GLOB`) usw. slhck vor 10 Jahren 3
Um Leerzeichen zu vermeiden, könnten Sie suchen. -maxdepth 1 -mindepth 1 -print0 | xargs -0` anstelle von `ls | xargs` :-) flob vor 9 Jahren 0

2 Antworten auf die Frage

29
Gordon Davisson

Sie verwirren zwei sehr unterschiedliche Eingaben: STDIN und Argumente. Argumente sind eine Liste von Zeichenfolgen, die dem Befehl beim Start zur Verfügung gestellt werden, normalerweise indem er sie nach dem Befehlsnamen (z . B. echo these are some argumentsoder rm file1 file2) angibt . STDIN ist dagegen ein Bytestrom (manchmal Text, manchmal nicht), den der Befehl nach dem Start (optional) lesen kann. Hier sind einige Beispiele (beachten Sie, dass catentweder Argumente oder STDIN verwendet werden können, es werden jedoch unterschiedliche Aktionen ausgeführt):

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, dass man STDIN-Eingabe in Argumente konvertiert:

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

echo Tatsächlich tut es mehr oder weniger das Gegenteil: Es konvertiert seine Argumente in STDOUT (das an das STDIN eines anderen Befehls geleitet 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. 
8
Alex P.

catnimmt Eingabe von STDINund rmnicht. Für solche Befehle müssen Sie Zeile für Zeile xargsdurchlaufen STDINund die Befehle mit Befehlszeilenparametern ausführen.