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?

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.


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 "."

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

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.


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

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`

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.


-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.

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.