Gibt es eine Möglichkeit, zwei Shell-Befehle, die mit find-exec aufgerufen werden, logisch zu kombinieren ?
Um beispielsweise alle .csv- Dateien auszudrucken , die den String foo zusammen mit seinem Vorkommen enthalten, möchte ich Folgendes tun:
find . -iname \*.csv -exec grep foo {} && echo {} \;
aber bash beschwert sich mit "fehlendem argument an '-exec'"
-exec
nacheinander oder ein einzelnes verwenden-exec sh -c 'grep foo "$0" && printf %s\\n "$0"' {} \;
.sh
(in diesem Fall{}
) übergeben wird, so etwas wie ist$1
und sein$0
wirdsh
. Aber in der Tat sind Sie richtig, das erste Argument zeigt sich als$0
. Das erste Argument als Name des aufrufenden Befehls ist nur eine Konvention, die in diesen Fällen nicht automatisch erzwungen wird.Antworten:
-exec
ist ein Prädikat, das einen Befehl ausführt (keine Shell) und basierend auf dem Ergebnis des Befehls (Beendigungsstatus Null oder Nicht-Null ) als wahr oder falsch ausgewertet wird .So:
würde drucken den Dateipfad , wenn
grep
Funde in der Datei foo. Stattdessen-print
können Sie ein anderes-exec
Prädikat oder ein beliebiges anderes Prädikat verwendenSiehe auch
!
und-o
finde Operatoren für Negation und oder .Alternativ können Sie eine Shell wie folgt starten:
Oder um zu vermeiden, dass für jede Datei eine Shell gestartet werden muss:
quelle
Das Problem, mit dem Sie konfrontiert sind, besteht darin, dass die Shell zuerst die Befehlszeile analysiert und zwei einfache Befehle sieht, die vom
&&
Operator getrennt werden :,find . -iname \*.csv -exec grep foo {}
undecho {} \;
. Zitiert&&
(find . -iname \*.csv -exec grep foo {} '&&' echo {} \;
) umgeht das, aber jetzt der Befehl ausgeführt durchfind
so etwas wiegrep
mit den Argumentenfoo
,wibble.csv
,&&
,echo
undwibble.csv
. Sie müssen anweisenfind
, eine Shell auszuführen, die den&&
Operator interpretiert :Beachten Sie, dass das erste Argument nach
sh -c SOMECOMMAND
ist$0
, nicht$1
.Sie können die Startzeit eines Shell-Prozesses für jede Datei speichern, indem Sie die Befehlsaufrufe mit gruppieren
-exec … +
. Übergeben Sie zur Vereinfachung der Verarbeitung einen Dummy-Wert$0
, um"$@"
die Dateinamen aufzulisten.Wenn der Shell-Befehl nur aus zwei durch getrennten Programmen besteht
&&
,find
kann der Job von selbst ausgeführt werden: Schreiben Sie zwei aufeinanderfolgende-exec
Aktionen, und die zweite wird nur ausgeführt, wenn die erste mit dem Status 0 beendet wird.(Ich gehe davon aus, dass
grep
undecho
nur zu Illustrationszwecken dienen, da-exec echo
diese durch ersetzt werden können-print
und die resultierende Ausgabe ohnehin nicht besonders nützlich ist.)quelle
./some-file: grep: command not found
Fehlermeldung angezeigt werden.-exec find sh -c '... "$1"' sh {} \;
hätte das Problem nicht. In Ihrem zweiten Suchbefehl ist ein Tippfehler enthalten.In diesem speziellen Fall würde ich tun:
find . -iname \*.csv -exec grep -l foo \{\} \;
Oder wenn Sie ack haben :
ack -al -G '.*\.csv' foo
Um Ihre eigentliche Frage zu beantworten, könnte Folgendes funktionieren:
find . -iname \*.csv -exec sh -c "grep foo {} && echo {}" \;
quelle