xargs -Ich ersetze-str Option Unterschied

16

Nach meinem Verständnis sollte Folgendes genau dasselbe bedeuten:

ls -1 | xargs file {}
ls -1 | xargs -I{} file {}

Wenn die Option -I nicht angegeben ist, wird standardmäßig -I {} verwendet.

Ich möchte alle Dateien im aktuellen Verzeichnis auflisten und den fileBefehl für jede einzelne ausführen . Einige haben Leerzeichen in ihren Namen. Ich bemerkte jedoch den Unterschied. Siehe unten:

$ ls -1
Hello World
$ ls -1 | xargs file {}
{}:    ERROR: cannot open `{}' (No such file or directory)
Hello: ERROR: cannot open `Hello' (No such file or directory)
World: ERROR: cannot open `World' (No such file or directory)
$ ls -1 | xargs -I{} file {}
Hello World: directory

Wenn -I {} explizit angegeben wird, werden Leerzeichen in Dateinamen wie erwartet behandelt.

vorausschauend
quelle
3
"Wenn die Option -I nicht angegeben ist, ist die Standardeinstellung -I {}" - dies ist zumindest bei GNU xargs falsch.
JJLIN
Ich verstehe meinen Fehler. Ich sollte entweder xargs fileoder angeben xargs -I{} file {}. Sollte nicht sein xargs file {}. Ich denke, wenn Sie -I {} explizit angeben, wird die Bash wie folgt behandelt file "Hello World". Ohne -I {} wird es als behandelt file Hello World.
foresightyj
1
(1) Diese Diskussion hat wenig mit der Shell (bash) zu tun. (2) Es ist gut, dass Sie die -1Option kennen ls, aber sie ist standardmäßig aktiviert, wenn die Ausgabe von lseine Datei oder eine Pipe ist, sodass Sie sie hier nicht benötigen. (3) Sie verwechseln -Imit der veralteten Option -i(Kleinbuchstaben I). -ifooist gleichbedeutend mit -Ifoo, aber schlicht -iist gleichbedeutend mit -I{}. Aber benutze -I{}. (4) Wenn du wirklich tun willst, was du sagst, warum nicht einfach sagen file *?
Scott
@Scott Meine ursprüngliche Absicht war es `find zu schreiben. -name "* .mov" | xargs -I {} file {} `, um alle mov-Dateien rekursiv zu finden und darauf auszuführen file. Aber ich fand ein einfacheres Beispiel mit ls. Du hast recht. Dafür file *ist das beste.
Foresightyj
1
finden hat -exec.
Cristian Ciupitu

Antworten:

20

Das -Ierfordert einen definierten Platzhalter. Die -iOption setzt voraus, dass {}es sich um den Platzhalter handelt. Dies war der Punkt, an dem ich man xargszumindest bei Cygwin und CentOS eine Annahme von {} fand .

xargs, das ohne eine der beiden Optionen aufgerufen wird, benötigt keinen Platzhalter und hängt die STDIN nur an das Ende der Argumente an.

Ergänzen echoSie einfach Ihre Beispiele, um zu sehen, was xargs tut:

$ ls -1
Hello World/

In Ihrem Beispiel wird aus Versehen Folgendes verwendet {}:

$ ls -1 | xargs echo file {}
file {} Hello World/

so filesieht der cmd args von {} Hello Worldund fehler.

Wenn Sie explizit {}in Ihrem xargs-Aufruf verwenden möchten :

$ ls -1 | xargs -i echo file {}
file Hello World/

Oder ohne Platzhalter:

$ ls -1 | xargs echo file
file Hello World/

xargs wie oben genannt benötigt das {} nicht. Das STDIN wird ohne Platzhalter an das Ende des Befehls angehängt. Die Verwendung von {} bedeutet normalerweise, dass Sie die STDIN irgendwo in der Mitte des Befehls ausführen möchten, wie in:

$ ls -1 | xargs -i mv {} /path/to/someplace/.
johnnyB
quelle
Das ist sehr klar. Ihre Antwort ist zwar etwas spät, aber das Lesen stärkt mein Verständnis.
Voraussichtlich