Ich habe ein Verzeichnis mit ~1M Dateien und muss nach bestimmten Mustern suchen. Ich weiß, wie man es für alle Dateien macht:
find /path/ -exec grep -H -m 1 'pattern' {} ;
Die volle Leistung ist nicht erwünscht (zu langsam). Mehrere erste Treffer sind in Ordnung, also habe ich versucht, die Anzahl der Zeilen zu begrenzen:
find /path/ -exec grep -H -m 1 'pattern' {} ; | head -n 5
Dies ergibt 5 Zeilen gefolgt von
find: `grep' terminated by signal 13
und find arbeitet weiter. Das ist hier gut erklärt. Ich habe versucht quit Aktion:
find /path/ -exec grep -H -m 1 'pattern' {} ; -quit
Dies gibt nur die erste Übereinstimmung aus.
Ist es möglich, die Ausgabe von find auf eine bestimmte Anzahl von Ergebnissen zu begrenzen (wie das Bereitstellen eines Arguments zum quit ähnlich wie head -n )?
Akzeptierte Antwort:
Da Sie bereits GNU-Erweiterungen verwenden (-quit , -H , -m1 ), können Sie genauso gut GNU grep verwenden 's -r Option, zusammen mit --line-buffered Daher gibt es die Übereinstimmungen aus, sobald sie gefunden werden, sodass es wahrscheinlicher ist, dass es von einem SIGPIPE getötet wird, sobald es die 6. Zeile schreibt:
grep -rHm1 --line-buffered pattern /path | head -n 5
Mit find , müssten Sie wahrscheinlich so etwas tun:
find /path -type f -exec sh -c '
grep -Hm1 --line-buffered pattern "[email protected]"
[ "$(kill -l "$?")" = PIPE ] && kill -s PIPE "$PPID"
' sh {} + | head -n 5
Das heißt, umschließen Sie grep in sh (Sie möchten immer noch so wenige grep ausführen Aufrufe wie möglich, daher der {} + ) und haben sh töte seinen Elternteil (find ), wenn grep stirbt an einem SIGPIPE.
Ein anderer Ansatz könnte darin bestehen, xargs zu verwenden als Alternative zu -exec {} + . xargs wird sofort beendet, wenn ein Befehl, den es erzeugt, durch ein Signal stirbt, also in:
find . -type f -print0 |
xargs -r0 grep -Hm1 --line-buffered pattern |
head -n 5
(-r und -0 GNU-Erweiterungen sind). Sobald grep schreibt in die kaputte Pipe, beides grep und xargs wird beendet und find wird sich auch selbst beenden, wenn es das nächste Mal etwas danach druckt. Ausführen von find unter stdbuf -oL könnte es früher passieren lassen.
Eine POSIX-Version könnte sein:
trap - PIPE # restore default SIGPIPE handler in case it was disabled
RE=pattern find /path -type f -exec sh -c '
for file do
awk '''
$0 ~ ENVIRON["RE"] {
print FILENAME ": " $0
exit
}''' < "$file"
if [ "$(kill -l "$?")" = PIPE ]; then
kill -s PIPE "$PPID"
exit
fi
done' sh {} + | head -n 5
Sehr ineffizient, da es mehrere Befehle für jede Datei ausführt.
Verwandte:Ubuntu – Wie sperrt man die Lüftergeschwindigkeit für AMD-GPU in Ubuntu 20.04?