Das funktioniert nicht. Kann dies in find gemacht werden? Oder muss ich xargs?
find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;
Das funktioniert nicht. Kann dies in find gemacht werden? Oder muss ich xargs?
find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;
Antworten:
Die Aufgabe, das Pipe-Symbol als Anweisung zum Ausführen mehrerer Prozesse zu interpretieren und die Ausgabe eines Prozesses in die Eingabe eines anderen Prozesses zu leiten, liegt in der Verantwortung der Shell (/ bin / sh oder gleichwertig).
In Ihrem Beispiel können Sie entweder Ihre Top-Level-Shell verwenden, um die Rohrleitungen wie folgt auszuführen:
find -name 'file_*' -follow -type f -exec zcat {} \; | agrep -dEOE 'grep'
In Bezug auf die Effizienz kostet dieses Ergebnis einen Aufruf des Funds, zahlreiche Aufrufe von zcat und einen Aufruf der Zustimmung.
Dies würde dazu führen, dass nur ein einziger zustimmender Prozess erzeugt wird, der die gesamte Ausgabe verarbeitet, die durch zahlreiche Aufrufe von zcat erzeugt wird.
Wenn Sie aus irgendeinem Grund mehrmals einverstanden sein möchten, können Sie Folgendes tun:
find . -name 'file_*' -follow -type f \
-printf "zcat %p | agrep -dEOE 'grep'\n" | sh
Dadurch wird eine Liste von Befehlen erstellt, die Pipes zum Ausführen verwenden, und diese dann an eine neue Shell gesendet, um sie tatsächlich auszuführen. (Das Weglassen des letzten "| sh" ist eine gute Möglichkeit, solche Befehlszeilen zu debuggen oder trocken auszuführen.)
In Bezug auf die Effizienz kostet dieses Ergebnis einen Aufruf des Funds, einen Aufruf des sh, zahlreiche Aufrufe von zcat und zahlreiche Aufrufe der Zustimmung.
Die effizienteste Lösung in Bezug auf die Anzahl der Befehlsaufrufe ist der Vorschlag von Paul Tomblin:
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
... was einen Aufruf von find, einen Aufruf von xargs, einige Aufrufe von zcat und einen Aufruf von acceptp kostet.
-exec sh -c "… | … " \;
.
die lösung ist einfach: über sh ausführen
... -exec sh -c "zcat {} | agrep -dEOE 'grep' " \;
-c
Option nicht übersehen . Andernfalls erhalten Sie eine rätselhafte No such file or directory
Fehlermeldung.
find -type f -name '*.mdds' -exec sh -c "echo {} | sed -e 's/_[0-9]\+//g' | xargs mv {}" \;
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
Sie können auch zu einer while
Schleife weiterleiten, die mehrere Aktionen für die gefundene Datei ausführen kann find
. Hier ist eine, um in jar
Archiven nach einer bestimmten Java-Klassendatei in einem Ordner mit einer großen Anzahl von jar
Dateien zu suchen
find /usr/lib/eclipse/plugins -type f -name \*.jar | while read jar; do echo $jar; jar tf $jar | fgrep IObservableList ; done
Der entscheidende Punkt ist, dass die while
Schleife mehrere Befehle enthält, die auf den übergebenen Dateinamen verweisen, der durch ein Semikolon getrennt ist. Diese Befehle können Pipes enthalten. In diesem Beispiel gebe ich den Namen der übereinstimmenden Datei wieder und liste dann auf, was in der Archivfilterung für einen bestimmten Klassennamen enthalten ist. Die Ausgabe sieht aus wie:
/usr/lib/eclipse/plugins/org.eclipse.core.contenttype.source_3.4.1.R35x_v20090826-0451.jar /usr/lib/eclipse/plugins/org.eclipse.core.databinding.observable_1.2.0.M20090902-0800 .jar org / eclipse / core / datenbindung / beobachtbar / liste / IObservableList .class /usr/lib/eclipse/plugins/org.eclipse.search.source_3.5.1.r351_v20090708-0800.jar / usr / lib / eclipse / plugins / org.eclipse.jdt.apt.core.source_3.3.202.R35x_v20091130-2300.jar /usr/lib/eclipse/plugins/org.eclipse.cvs.source_1.0.400.v201002111343.jar / usr / lib / eclipse / plugins / org.eclipse.help.appserver_3.1.400.v20090429_1800.jar
In meiner Bash-Shell (xubuntu10.04 / xfce) wird der übereinstimmende Klassenname wirklich fett gedruckt, da fgrep
die übereinstimmende Zeichenfolge hervorgehoben wird. Dies macht es wirklich einfach, die Liste von Hunderten von jar
Dateien zu durchsuchen, die durchsucht wurden, und leicht Übereinstimmungen zu sehen.
Unter Windows können Sie dasselbe tun mit:
for /R %j in (*.jar) do @echo %j & @jar tf %j | findstr IObservableList
Beachten Sie, dass unter Windows das Befehlstrennzeichen '&' not ';' ist. und dass das '@' das Echo des Befehls unterdrückt, um eine ordentliche Ausgabe zu liefern, genau wie die Linux-Find-Ausgabe oben; Obwohl findstr
die übereinstimmende Zeichenfolge nicht fett gedruckt ist, müssen Sie sich die Ausgabe etwas genauer ansehen, um den Namen der übereinstimmenden Klasse zu sehen. Es stellt sich heraus, dass der Windows-Befehl 'for' einige Tricks kennt, wie das Durchlaufen von Textdateien ...
genießen
Ich fand, dass das Ausführen eines String-Shell-Befehls (sh -c) am besten funktioniert, zum Beispiel:
find -name 'file_*' -follow -type f -exec bash -c "zcat \"{}\" | agrep -dEOE 'grep'" \;
Wenn Sie nach einer einfachen Alternative suchen, können Sie dies mit einer Schleife tun:
for i in $(find -name 'file_*' -follow -type f);do zcat $i | agrep -dEOE 'grep');done
oder allgemeinere und leicht verständliche Form:
for i in $(YOUR_FIND_COMMAND);do YOUR_EXEC_COMMAND_AND_PIPES );done
und ersetzen Sie {} durch $ i in YOUR_EXEC_COMMAND_AND_PIPES