Gibt es eine Möglichkeit, den find
Befehl sofort nach dem Finden der ersten Übereinstimmung zum Stoppen zu zwingen ?
Gibt es eine Möglichkeit, den find
Befehl sofort nach dem Finden der ersten Übereinstimmung zum Stoppen zu zwingen ?
Antworten:
Mit GNU oder FreeBSD find
können Sie das -quit
Prädikat verwenden:
find . ... -print -quit
Das NetBSD- find
Äquivalent:
find . ... -print -exit
Wenn Sie nur den Namen drucken und davon ausgehen, dass die Dateinamen keine Zeilenumbrüche enthalten, können Sie Folgendes tun:
find . ... -print | head -n 1
Das wird nicht find
nach dem ersten Match aufhören , sondern möglicherweise, je nach Timing und Pufferung nach dem zweiten Match oder (viel) später. Grundsätzlich find
wird mit einem SIGPIPE beendet werden , wenn es um Ausgang etwas versucht , während head
schon weg, da sie bereits gelesen und angezeigt , um die erste Zeile der Eingabe.
Beachten Sie, dass nicht alle Shells find
nach head
der Rückkehr auf diesen Befehl warten . Die Bourne-Shell- und AT & T-Implementierungen von ksh
(wenn nicht interaktiv) und yash
(nur wenn diese Pipeline der letzte Befehl in einem Skript ist) würden dies nicht tun, sodass sie im Hintergrund ausgeführt würden. Wenn Sie dieses Verhalten lieber in einer Shell sehen möchten, können Sie das oben stehende jederzeit ändern in:
(find . ... -print &) | head -n 1
Wenn Sie mehr tun als nur die Pfade der gefundenen Dateien zu drucken, können Sie diesen Ansatz ausprobieren:
find . ... -exec sh -c 'printf "%s\n" "$1"; kill "$PPID"' sh {} \;
(Ersetzen printf
Sie sie durch das, was Sie mit dieser Datei tun würden.)
Dies hat den Nebeneffekt find
, dass ein Exit-Status zurückgegeben wird, der die Tatsache widerspiegelt, dass er getötet wurde.
Tatsächlich führt die Verwendung des Signals SIGPIPE anstelle von SIGTERM ( kill -s PIPE
anstelle von kill
) dazu, dass einige Shells über diesen Tod leiser sind (aber dennoch einen Ausgangsstatus ungleich Null zurückgeben würden).
if [[ $(find ... -print -quit) ]]; then ...
Sie in Bash und GNU Find Folgendes tun: Es wird nur getestet, ob der Ausdruck überhaupt gefunden wird.
$(…)
Teil in Anführungszeichen zu setzen, wenn Sie nur die einzelnen Klammern verwenden ( [ … ]
).
[
ist ein Standardbefehl. Es ist nicht so sehr dieser Befehl, der schrecklich ist, sondern die Art und Weise, wie Bourne-ähnliche Shells Befehlszeilen analysieren. [[...]]
ist ein ksh-Konstrukt, das in verschiedenen Shells eigene Probleme hat. Zum Beispiel, bis vor kurzem [[ $(...) ]]
würde nicht funktionieren zsh
(Sie brauchten [[ -n $(...) ]]
). Abgesehen davon zsh
, dass Sie Anführungszeichen in benötigen [[ $a = $b ]]
, [[ =~ ]]
weist das inkompatible Unterschiede zwischen Implementierungen und sogar zwischen Versionen für Bash und einigen Bugs auf. Persönlich bevorzuge ich [
.
...
? .
find . -name something -print -quit
Beendet die Suche nach dem ersten Treffer nach dem Drucken.
Suche nach einer bestimmten Anzahl von Übereinstimmungen beenden und Ergebnisse ausdrucken:
find . -name something -print | head -n 5
Überraschenderweise beendet head die Zeichenfolge nach 5 Übereinstimmungen, obwohl ich nicht weiß, wie oder warum.
Es ist sehr einfach zu testen. Lassen Sie finden suchen ein auf Wurzel , die Tausende, vielleicht sogar mehr Spiele während der Einnahme von mindestens einer Minute oder mehr zur Folge hätte. Wenn "find" in "head" umgeleitet wird, wird "find" nach der angegebenen Anzahl von Zeilen, die in head definiert sind, beendet (Standardeinstellung head zeigt 10, verwenden Sie "head -n", um Zeilen anzugeben).
Beachten Sie, dass dies beendet wird, nachdem "head -n" die angegebene Anzahl von Zeilenvorschubzeichen erreicht hat. Daher zählt jede Übereinstimmung, die mehrere Zeilenvorschubzeichen enthält, entsprechend.
Zu Unterhaltungszwecken gibt es hier einen Lazy-Find-Generator in Bash. In diesem Beispiel wird ein Ring über die Dateien im aktuellen Verzeichnis generiert. Lies so viele du willst kill %+
(vielleicht nur 1)
#!/usr/bin/env bash
unset -v files n
trap 'kill "$x_PID"' EXIT
coproc x while :; do
find . -type f -maxdepth 1 -exec sh -c "$(</dev/fd/3)" _ {} +
done 4<&0 <<\EOF 3<&0 <&4-
for x; do
read -r _
printf '%s\0' "$x"
done
EOF
while
echo >&${x[1]}
IFS= read -rd '' -u "$x" 'files[n++]'
do
printf '%q ' "${files[@]}"
echo
sleep .2
done
grep gibt auch zurück, wenn es mit dem Flag verwendet wird -m
, also mit
find stuff | grep -m1 .
Es wird nach der ersten von find ausgegebenen Zeile zurückgegeben.
Der Unterschied zwischen diesem und diesem find stuff -print -quit | head -1
ist, dass grep, wenn die Suche schnell genug ist, möglicherweise nicht in der Lage ist, den Prozess rechtzeitig anzuhalten (obwohl dies nicht wirklich wichtig ist), während es bei einer langen Suche Zeit spart, eine Menge nicht benötigter Dokumente zu drucken Linien.
dies funktioniert stattdessen mit busybox find, obwohl da busybox grep auch -m
nicht wirklich benötigt wird
find /tmp/stuff -exec "sh" "-c" "eval 'echo {}; { kill \$PPID; }'" \;
Dies gibt eine Nachricht darüber aus, dass der Suchvorgang das (normalerweise) sigterm-Signal empfangen hat, aber diese Ausgabe gehört zur laufenden Shell, nicht zum find-Befehl, sodass sie nicht mit der Befehlsausgabe in Konflikt gerät, was bedeutet, dass Pipes oder Umleitungen nur die Zeile ausgeben von find abgestimmt.