Jak wykryć, czy „znaleźć” znalazło jakieś dopasowania?


16

Czy istnieje idiomatyczny sposób wykrycia, czy „znajdź” znalazł jakieś dopasowania? Obecnie używam

COUNT=`find ... | wc -l`
if [ "$COUNT" -gt 0 ]; then

ale wydaje mi się to trochę pośrednie. Ponadto chciałbym znaleźć, aby przestał szukać, gdy znajdzie pasujący element, więc nie marnuje czasu i wysiłku. Muszę tylko wiedzieć, czy są jakieś pasujące pliki.

Aktualizacja: Popełniłem błąd, pisząc moje pytanie bez kodu przede mną: używam wc -lw innym przypadku, w którym i tak muszę znać całkowitą liczbę znalezionych plików. W przypadku, gdy testuję tylko, czy są jakieś dopasowania, użyłem if [ -z $(find …) ].

Odpowiedzi:


17

Jeśli wiesz, że masz GNU find, użyj, -quit aby zatrzymać go po pierwszym dopasowaniu.

Przenośnie potokuj wyjście finddo head -n 1. W ten sposób findumrze zepsuta rura po kilku dopasowaniach (gdy zostanie wypełniony headbufor wejściowy).

Tak czy inaczej, nie musisz wcsprawdzać, czy łańcuch jest pusty, powłoka może to zrobić sama.

if [ -n "$(find … | head -n 1)" ]; then …

Interesujące ... Myślałem, że -ndotyczy tylko zmiennych „zdefiniowanych” ($ abc, $ xyz itp.), Ale przypuszczam, że $ (...) jest „zdefiniowaną” zmienną temp. +1 ... (i po prostu ostatnio czytałem, że używanie -njest ryzykowne, chyba że masz pewność, że zmienna nie została już zadeklarowana i jest „nieużywana)… ale temp nie będzie miał takiej możliwości… niezainicjowany kontra pusty
Peter.O

2
@fred: Przeciwnie, -nsprawdza, czy łańcuch jest pusty, nie ma to nic wspólnego ze zmiennymi. To, co przeczytałeś, prawdopodobnie powiedziało, że użycie -nnie sprawdza, czy zmienna jest zdefiniowana: -n "$foo"jest fałszywe, jeśli foojest zdefiniowane, ale puste, i wyświetla komunikat o błędzie pod set -u. [ -n "${foo+1}" ]niezawodnie sprawdza, czy foojest ustawiony, ale identyczne traktowanie pustych i nieuzbrojonych zmiennych jest zwykle dobrym pomysłem: [ -n "${foo:+1}" ]lub po prostu, [ -n "$foo" ]jeśli się nie martwisz set -u.
Gilles „SO- przestań być zły”

Dzięki! Nie mam -quitdostępnego, ale przesyłanie strumieniowe do head -n 1działa (tak jak to head -c 1, co zatrzymuje się nawet wcześniej, ale prawdopodobnie z nieistotną korzyścią). Popełniłem też błąd, pisząc moje pytanie bez kodu przede mną: używam wc -lw innym przypadku, w którym muszę znać całkowitą liczbę znalezionych plików. W przypadku, gdy testuję tylko, czy są jakieś dopasowania, użyłem if [ -z `find … ` ].
Chris Page

6

Możesz użyć -quitakcji, aby zatrzymać po pierwszym meczu. Prawdopodobnie będziesz chciał połączyć to z inną akcją (jak -print), inaczej nie będziesz w stanie stwierdzić, czy coś znalazło.

Na przykład find ... -print -quitwydrukuje ścieżkę pierwszego pasującego pliku, a następnie zakończy działanie. Lub możesz użyć -printf 1 -quitdo wydrukowania 1, jeśli jest dopasowanie i nic, jeśli nie ma.

findStatus wyjścia odzwierciedla, czy podczas wyszukiwania wystąpiły błędy, a nie czy coś znalazł, więc musisz sprawdzić jego wynik, aby sprawdzić, czy istnieje dopasowanie.


-quitjest rozszerzeniem GNU. Nie będzie działać na systemach wykorzystujących inne implementacje find (1), takich jak OS X, BSD i prawdopodobnie większość komercyjnych Unices.
Warren Young

Dzięki, warto wiedzieć, na wypadek, gdy używam innego systemu. Niestety, ani -quit, ani -printf nie są dostępne w moim (Mac OS X).
Chris Page

4

Wyjście 0 jest łatwe do znalezienia, wyjście> 0 jest trudniejsze, ponieważ zwykle dzieje się tak tylko z błędem. Jednak możemy to zrobić:

if find -type f -exec false {} +
then
  echo 'nothing found'
else
  echo 'something found'
fi

Zauważ, że to rozwiązanie jest bardziej wydajne niż użycie podpowłoki; wykonanie false jest z pewnością szybsze niż wykonanie nawet Dasha:

$ cat alfa.sh bravo.sh charlie.sh delta.sh
find -name non-existing-file -exec false {} +
find -name existing-file -exec false {} +
[ "$(find -name non-existing-file)" ]
[ "$(find -name existing-file)" ]

$ strace dash alfa.sh | wc -l
807

$ strace dash bravo.sh | wc -l
1141

$ strace dash charlie.sh | wc -l
1184

$ strace dash delta.sh | wc -l
1194

0

Możesz owinąć go w stan powłoki, np .:

[ "$(find . ...)" '!=' '' ] && echo Found || echo Not found

Gdzie ...jest twój warunek dopasowania, np -name *.txt.

Kilka innych przykładów:

[ "$(find /etc -name hosts)" ] && echo True || echo False
[ ! -z "$(find /etc -name hosts)" ] && echo True || echo False
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.