Czy istnieje sposób, aby zmusić findpolecenie do zatrzymania zaraz po znalezieniu pierwszego dopasowania?
Czy istnieje sposób, aby zmusić findpolecenie do zatrzymania zaraz po znalezieniu pierwszego dopasowania?
Odpowiedzi:
W GNU lub FreeBSD findmożesz użyć -quitpredykatu:
find . ... -print -quit
Odpowiednik NetBSD find:
find . ... -print -exit
Jeśli wszystko, co robisz, to drukujesz nazwę i zakładając, że nazwy plików nie zawierają znaków nowej linii, możesz:
find . ... -print | head -n 1
Nie zatrzyma się to findpo pierwszym meczu, ale możliwe, że w zależności od czasu i buforowania przy drugim meczu lub (znacznie) później. Zasadniczo findzostanie zakończone SIGPIPE, gdy spróbuje coś wyrenderować, gdy headjuż go nie ma, ponieważ już odczytał i wyświetlił pierwszy wiersz danych wejściowych.
Zauważ, że nie wszystkie powłoki będą czekać na to findpolecenie po headjego zwróceniu. Implementacje powłoki Bourne'a i implementacji AT&T ksh(gdy nie są interaktywne) i yash(tylko jeśli ten potok jest ostatnim poleceniem w skrypcie) nie, pozostawiając działające w tle. Jeśli wolisz zobaczyć takie zachowanie w dowolnej powłoce, zawsze możesz zmienić powyższe na:
(find . ... -print &) | head -n 1
Jeśli robisz więcej niż drukowanie ścieżek znalezionych plików, możesz wypróbować następujące podejście:
find . ... -exec sh -c 'printf "%s\n" "$1"; kill "$PPID"' sh {} \;
(zamień na printfcokolwiek, co robisz z tym plikiem).
Ma to jednak efekt uboczny findzwrócenia statusu wyjścia odzwierciedlającego fakt, że został zabity.
Właściwie użycie sygnału SIGPIPE zamiast SIGTERM ( kill -s PIPEzamiast kill) spowoduje, że niektóre pociski będą milczały na temat tej śmierci (ale nadal zwrócą niezerowy status wyjścia).
if [[ $(find ... -print -quit) ]]; then ...Testuje tylko, czy w ogóle coś wydrukowano.
$(…)część w cudzysłów, jeśli używasz tylko pojedynczych nawiasów ( [ … ]).
[to standardowe polecenie. To nie tyle straszne polecenie, co sposób, w jaki powłoki Bourne'a analizują wiersze poleceń. [[...]]jest konstrukcją ksh, która ma własne problemy w różnych powłokach. Na przykład do niedawna [[ $(...) ]]nie działał zsh(trzeba [[ -n $(...) ]]). Z wyjątkiem zsh, potrzebujesz cytatów [[ $a = $b ]], [[ =~ ]]ma niezgodne różnice między implementacjami, a nawet między wersjami bash i kilkoma błędami w niektórych. Osobiście wolę [.
...? .
find . -name something -print -quit
Kończy wyszukiwanie po pierwszym dopasowaniu po wydrukowaniu.
Zakończ wyszukiwanie po określonej liczbie dopasowań i wydrukuj wyniki:
find . -name something -print | head -n 5
Zaskakujące - głowa kończy teraz ciąg po 5 meczach, chociaż nie wiem jak i dlaczego.
Jest to bardzo łatwe do przetestowania. Po prostu pozwól odnaleźć szukać na korzeń, który powodowałby tysiące, a może nawet więcej meczów podczas przyjmowania co najmniej minutę lub więcej. Ale po podłączeniu do „head” „find” zakończy się po określonej liczbie linii zdefiniowanych w head (domyślna głowa pokazuje 10, użyj „head -n”, aby określić linie).
Zauważ, że zakończy się ono, gdy „head -n” osiągnie określoną liczbę znaków nowej linii, a zatem każde dopasowanie zawierające wiele znaków nowej linii będzie odpowiednio liczone.
Dla celów rozrywkowych, oto leniwy generator znajdujący się w Bash. Ten przykład generuje pierścień nad plikami w bieżącym katalogu. Przeczytaj tyle, ile chcesz kill %+(może tylko 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 zwraca również, jeśli jest używane z flagą -m, więc z
find stuff | grep -m1 .
powróci po pierwszym wierszu wydrukowanym przez find.
Różnica między tym a tym, find stuff -print -quit | head -1że jeśli wyszukiwanie jest wystarczająco szybkie, grep może nie być w stanie zatrzymać procesu na czas (nie ma to jednak znaczenia), a jeśli wyszukiwanie jest długie, zaoszczędzę znaleźć wiele niepotrzebnych wydruków linie.
to zamiast tego działa z funkcją busybox find, chociaż skoro busybox grep również -mgo ma , to nie jest tak naprawdę potrzebne
find /tmp/stuff -exec "sh" "-c" "eval 'echo {}; { kill \$PPID; }'" \;
to wypluje komunikat o tym, że proces znajdowania otrzymał (zwykle) sygnał sigterm, ale to wyjście należy do działającej powłoki, a nie polecenia find, więc nie zadziera z wyjściem polecenia, co oznacza, że potoki lub przekierowania wyprowadzą tylko linię dopasowane przez find.