Dlaczego moje znalezisko nie jest rekurencyjne?

65

Korzystam z następującego polecenia, ale nie jest ono wykonywane rekurencyjnie:

find . -name *.java

Wiem, że pliki java znajdują się dalej w bieżącym katalogu, ale wykonuje tylko findw bieżącym katalogu. Używam OS X, 10.9.

użytkownik11498
źródło
@Gilles: Te pytania i odpowiedzi są znacznie bardziej przejrzyste i mniej zlokalizowane niż duplikat - jeśli jedno z nich powinno zostać zamknięte, to drugie.
złotowłosa

Odpowiedzi:

88

Problem polega na tym, że nie podałeś swojego -nameparametru. Zrób to zamiast tego:

find . -name '*.java'

Wyjaśnienie

Bez cudzysłowów powłoka interpretuje ją *.javajako wzorzec glob i przed przekazaniem go rozwija do dowolnych nazw plików pasujących do glob find. W ten sposób, gdybyś miał, powiedzmy, foo.javaw bieżącym katalogu, findrzeczywisty wiersz poleceń wyglądałby następująco:

find . -name foo.java

co oczywiście spowoduje wyświetlenie listy plików tylko w bieżącym katalogu (chyba że zdarzy się, że będziesz mieć pliki o podobnych nazwach w dalszej części drzewa).

Cytowanie zapobiega ekspansji globu i przekazuje wiersz poleceń do stanu „ findjak jest”.

Nawiasem mówiąc, gdyby glob nie pasował (brak *.javaplików w bieżącym katalogu), dostaniesz jedno z dwóch zachowań w zależności od tego, jak twoja powłoka jest skonfigurowana do obsługi globów, które nie pasują (jest to regulowane przez nullglobopcję w Bash , na przykład):

  1. Jeśli glob, który nie pasuje, nie zostanie rozwinięty przez powłokę, find(przypadkowo, pamiętajcie) wykaże prawidłowe zachowanie.
  2. Jeśli glob, który nie pasuje, zostanie rozwinięty przez powłokę w pusty ciąg, findnarzeka, że ​​brakuje mu argumentu -name.
Joseph R.
źródło
20

Miałem podobną sytuację, w której otaczałem wartość -name w cudzysłowie, ale nadal nie otrzymywałem wszystkich trafień znalezienia, na które liczyłem. Doszedłem do wniosku, że dzieje się tak z powodu dowiązań symbolicznych i na pewno tak było. Jeśli chcesz wymusić szukanie poprzez przeszukiwanie dowiązań symbolicznych, możesz zmodyfikować polecenie w następujący sposób:

find -L . -name '*.java'
Gaoagong
źródło
Symlinks były również moim problemem. -followjest bardziej czytelnym synonimem -L, pod warunkiem, że umieścisz go przed innymi parametrami.
Noumenon
0

Escape the *

find . -name \*.java
Stuart Cardall
źródło