Czy mogę sprawić, aby `find` zwrócił wartość inną niż 0, gdy nie znaleziono pasujących plików?

46

Nawet gdy /tmpnie ma wywołanego pliku something, wyszukiwanie go za pomocą findzwróci 0:

  $ find /tmp -name something 
  $ echo $?
  0

Jak mogę uzyskać niezerowy status wyjścia, gdy findniczego nie znajdziesz?

Yael
źródło

Odpowiedzi:

44

Oto jedna linijka, która moim zdaniem robi to, co chcesz:

find /tmp -name something | egrep '.*'

Status zwracany będzie, 0gdy coś zostanie znalezione, a w przeciwnym razie niezerowy.

Jeśli musisz także uchwycić wyniki finddo dalszego przetwarzania, odpowiedź Svena to pokryła.

Steven Monday
źródło
14
Kropka *na egrepregex jest całkowicie zbędne. Ponieważ nie używasz egrepskładni wyrażeń regularnych, zwykły stary grepmoże być o kilka mikrosekund szybszy.
tripleee
nauczyłem się używaćfind ... | read
Sam
14

Najprostsze rozwiązanie, które nie drukuje, ale wychodzi 0 po znalezieniu wyników

find /tmp -name something | grep -q "."
Matt Kneiser
źródło
2
Podwójne cudzysłowy nie mają tutaj sensu.
haridsv
Podczas gdy podwójne cudzysłowy nie pełnią żadnej funkcji kodu, czytelnikowi lepiej widać, że znak kropki jest wyrażeniem regularnym, a nie katalogiem.
Dharma Bellamkonda
13

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
Steven Penny
źródło
2
O ile wiem, to nie działa. Wydaje się, że kod wyjścia findnie zależy od kodów wyjścia -execuruchomionych przez niego programów .
Chris
@Chris pracuje dla mnie i 4 osób, które głosowały
Steven Penny
przykład błędnie fałszywego wyniku tego rozwiązania: znajdź / istniejący-punkt-początkowy / nieistniejący-punkt-początkowy nazwa-pliku-istniejący-punkt początkowy -wykonaj false {} +
Gerald Schade
2
Działa to poprawnie i jest udokumentowane (chociaż ukryte w execsekcji, a nie pod wartością zwracaną). Nie potrafi rozróżnić niczego, co nie zostało znalezione, i popełnił błąd (np. Gdy został wywołany w nieistniejącym punkcie początkowym).
Tgr
Jeśli potrzebujesz tej funkcjonalności - tak
Gerald Schade
7

Po znalezieniu tego pytania podczas próby rozwiązania problemu z Puppet (zmiana uprawnień do folderów w katalogu, ale nie do samego katalogu), wydaje się, że działa:

! test -z $(find /tmp -name something)

Mój konkretny przypadek użycia jest następujący:

! test -z $(find /home -mindepth 1 -maxdepth 1 -perm -711)

Który zakończy kod 1, jeśli polecenie find nie znajdzie plików z wymaganymi uprawnieniami.

shearn89
źródło
Kilka rozwiązań (nie wypróbowałem ich wszystkich) tutaj nie działa na komputerze Mac; to zrobiło.
Alex Hall
5

To nie jest możliwe. Znajdź zwraca 0, jeśli zakończy się pomyślnie, nawet jeśli nie znalazł pliku (co jest poprawnym wynikiem, nie oznacza błędu, gdy plik rzeczywiście nie istnieje).

Cytując znalezioną stronę podręcznika

STATUS WYJŚCIA

znajdź wyjścia ze statusem 0, jeśli wszystkie pliki zostaną pomyślnie przetworzone, większe niż 0, jeśli wystąpią błędy. Jest to celowo bardzo szeroki opis, ale jeśli zwracana wartość jest różna od zera, nie należy polegać na poprawności wyników wyszukiwania.

W zależności od tego, co chcesz osiągnąć, możesz spróbować znaleźć -printnazwę pliku i przetestować na podstawie wyniku:

#!/bin/bash
MYVAR=`find . -name "something" -print`
if [ -z "$MYVAR" ]; then
    echo "Notfound"
else
   echo $MYVAR
fi
Sven
źródło
Z pewnością jest to możliwe , choć nie tak solidne, jak mogłoby się wydawać.
Ruslan
Strona podręcznika jest źle zorganizowana; to, co powiedział Ruslan, jest udokumentowane w opcji exec/ execdir(używane z +):If any invocation returns a non-zero value as exit status, then find returns a non-zero exit status.
Tgr
1

Uważam, że jest to najbardziej zwięzła i bezpośrednia metoda:

test `find /tmp/ -name something -print -quit 2>/dev/null`
Danorton
źródło
2
W takim przypadku, jeśli find miał błąd, wypisze wynik do / dev / null, zwróci niezerowe wyjście, a następnie ustawi wartość na 0 za pomocą polecenia testowego.
Jeff Ferland
Nie wierzę, że to prawda. Opisz swój przykład. Jeśli wystąpi błąd i znajdź wyjście, łańcuch będzie pusty, a test zwróci wartość niezerową.
danorton
Nie jestem pewien, jaki może być twój przykład, ale przypadkowo go pominąłem -print -quit, co może rozwiązać problem.
danorton
Być może inna osoba, która przegłosowała (prawdopodobnie z tego samego powodu), może podać przeciwny przykład?
danorton
1
Okej, po prostu nie lubisz mojego stylu. W moich przypadkach użycia wszelkie znalezione błędy mogą zgłaszać hałas lub tak poważne, że pojawią się gdzie indziej. W każdym razie ta metoda poprawnie odpowiada na ostateczne pytanie: „Czy na ścieżce jest dostępny plik o podanej nazwie”. Błąd zwróci poprawną odpowiedź „Nie”. Jeśli chcę się dowiedzieć, dlaczego nie, mogę dodać bardziej złożony kod, który odpowiada na pytania, które nie zostały tutaj postawione.
danorton
0

Oto mały skrypt, który zadzwoniłem test.py. Poprawia inne metody zamieszczone w tym, że zwróci kod błędu, jeśli jest ustawiony, a dodatkowo ustawia jeden, jeśli find nie wyświetlał żadnych plików:

from subprocess import Popen
import sys

p = Popen(['find'] + sys.argv)
out, err = p.communicate()
if p.returncode:
    sys.exit(p.returncode)
if not out:
    sys.exit(1)

Oto wynik działania wiersza polecenia:

$ python test.py . -maxdepth 1 -name notthere
$ echo $?
1
$ find . -maxdepth 1 -name notthere
$ echo $?
0
$ find . -failedarg
find: unknown predicate `-failedarg'
$ echo $?
1

Następnie, aby uzyskać wynik, w którym znaleziono błędy, ale znaleziono pliki:

$ ls -lh
$ d---------  2 jeff users   6 Feb  6 11:49 noentry
$ find .
.
./noentry
find: `./noentry': Permission denied
$ echo $?
1
$ find . | egrep '.*'
.
./noentry
find: `./noentry': Permission denied
$ echo $?
0
python ../test.py 
../test.py
$ echo $?
1

Następnie, jeśli chcesz listę plików, możesz skorzystać z -print 0przekazanej findi podzielić zmienną out na wartości null lub możesz po prostu dodać dla niej instrukcję print.

Jeff Ferland
źródło
-1

Nie tylko findzwraca kody stanu wyjścia jako zero, gdy się powiedzie. W unixie, cokolwiek polecenie, które wykonasz, jeśli się powiedzie, to zwraca status wyjścia jako zero.

Informatica-Oracle-Unix
źródło