it-swarm.com.de

Wie verwende ich> in einem xargs-Befehl?

Ich möchte einen bash-Befehl finden, mit dem ich jede Datei in einem Verzeichnis abfragen und die Ausgabe dieses Abfrages in eine separate Datei schreiben kann. Meine Vermutung wäre gewesen, so etwas zu tun

ls -1 | xargs -I{} "grep ABC '{}' > '{}'.out"

aber soweit ich weiß, mag xargs die doppelten Anführungszeichen nicht. Wenn ich jedoch die doppelten Anführungszeichen entferne, leitet der Befehl die Ausgabe des gesamten Befehls in eine einzelne Datei mit dem Namen '{}' anstatt in eine Reihe einzelner Dateien um.

Kennt jemand eine Möglichkeit, dies mit xargs zu tun? Ich habe dieses grep-Szenario nur als Beispiel verwendet, um mein Problem mit xargs zu veranschaulichen, sodass alle Lösungen, die keine xargs verwenden, für mich nicht geeignet sind.

147
Jesse Shieh

Machen Sie nicht den Fehler, dies zu tun:

sh -c "grep ABC {} > {}.out"

Dies wird unter vielen Bedingungen, einschließlich funky Dateinamen, brechen und ist unmöglich, richtig zu zitieren. Ihre {} muss immer ein einzelnes, vollständig separates Argument zum Befehl sein, um Fehler bei der Codeinjektion zu vermeiden. Was Sie tun müssen, ist Folgendes:

xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}

Gilt sowohl für xargs als auch für find.

Übrigens, verwende niemals xargs ohne das -0 -Option (es sei denn, es handelt sich um eine sehr seltene und kontrollierte einmalige interaktive Verwendung, bei der Sie sich keine Sorgen um die Zerstörung Ihrer Daten machen).

Analysieren Sie auch nicht ls. Je. Verwenden Sie stattdessen globbing oder find: http://mywiki.wooledge.org/ParsingLs

Verwenden Sie find für alles, was eine Rekursion erfordert, und eine einfache Schleife mit einem Glob für alles andere:

find /foo -exec sh -c 'grep "$1" > "$1.out"' -- {} \;

oder nicht rekursiv:

for file in *; do grep "$file" > "$file.out"; done

Beachten Sie die korrekte Verwendung von Anführungszeichen.

181
lhunath

Eine Lösung ohne xargs lautet wie folgt:

find . -mindepth 1 -maxdepth 1 -type f -exec sh -c "grep ABC '{}' > '{}.out'" \;

... und das gleiche kann gemacht werden mitxargs, es stellt sich heraus:

ls -1 | xargs -I {} sh -c "grep ABC '{}' > '{}.out'"

Edit: einfache Anführungszeichen nach Bemerkung von lhunath .

39
Stephan202

Ich gehe davon aus, dass Ihr Beispiel nur ein Beispiel ist und dass Sie möglicherweise> für andere Dinge benötigen. GNU Parallel http://www.gnu.org/software/parallel/ kann Ihre Rettung sein. Es sind keine zusätzlichen Anführungszeichen erforderlich, solange Ihre Dateinamen dies nicht tun enthalten\n:

ls | parallel "grep ABC {} > {}.out"

Wenn Sie Dateinamen mit\n haben:

find . -print0 | parallel -0 "grep ABC {} > {}.out"

Als zusätzlichen Bonus erhalten Sie die Jobs parallel ausgeführt.

Bearbeiten.

Sie können GNU Parallel einfach folgendermaßen installieren:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel

Sehen Sie sich die Intro-Videos an, um mehr zu erfahren: http://pi.dk/1

10 Sekunden Installation:

wget pi.dk/3 -qO - | sh -x
14
Ole Tange