Jak zatrzymać zejście znaleziska do znalezionych katalogów?

24

Chcę znaleźć wszystkie katalogi z określonym ciągiem znaków, aby móc wykonać kolejne wyszukiwanie w zawartych w nich plikach.

Więc nie chcę tracić czasu na ./my-search-term/dir/my-search-termitp.

Jak mogę zatrzymać rekursję, gdy znajdę pierwszy katalog wyszukiwanych terminów?

Stephen
źródło
3
Czy próbowałeś znaleźć z -prune? Ze strony podręcznika: „jeśli plik jest katalogiem, nie schodź do niego. Jeśli podano -depth, false; brak efektu. Ponieważ -delete oznacza -depth, nie można użyć -prune i -delete razem”.
laebshade
1
@laebshade dlaczego nie umieścisz tego w odpowiedzi?
jw013,
@ jw013 W tym czasie nie miałem czasu udzielić bardziej szczegółowej odpowiedzi.
laebshade

Odpowiedzi:

17

-pruneDziałanie sprawia, że findnie recurse do katalogu. Możesz połączyć go z inną akcją, np. -exec(Kolejność -prunei -execnie ma znaczenia, o ile -prunejest wykonywana w obu kierunkach).

find . -name my-search-term -prune -exec find {} … \;

Zauważ, że zagnieżdżanie findwewnątrz find -execmoże być nieco problematyczne: nie możesz używać -execwewnątrz find, ponieważ terminator byłby postrzegany jako terminator przez zewnętrzną find. Możesz obejść ten problem, wywołując powłokę, ale uważaj na cytowanie.

find . -name my-search-term -prune -exec sh -c '
    find "$@" … -exec … {\} +
' _ {} +
Gilles „SO- przestań być zły”
źródło
Czy nawiasy w pierwszym poleceniu są konieczne? -prunezwraca true i może być postawione przed -exec.
rozcietrzewiacz
@rozcietrzewiacz Nie, nie są konieczne. Zwyczaj mający -otam, myślę. I wydaje mi się, że stawianie -prunewcześniej -execjest bardziej czytelne.
Gilles 'SO - przestań być zły'
Dzięki, wcześniej nie korzystałem z tej -pruneopcji.
haridsv
W moim przypadku użycia tego polecenia: mkdir -p x1 x2; touch x1/x11 x1/x12 x2/x21 x2/x22; find . -name 'x1*' -exec rm -rf {} \;daje błąd: find: ./x1: No such file or directory. Rozwiązaniem jest dodanie -prunena końcu findpolecenia.
haridsv
(1) Niektóre wersje findrozwinięcia, {}nawet jeśli pojawia się jako podciąg argumentu do -exec. Taka wersja finddusi się przy drugim poleceniu, ponieważ {}w findpoleceniu wewnętrznym (w poleceniu powłoki) zostanie zastąpiona nazwą katalogu znalezionego w zewnętrznym find. Możesz to naprawić, mówiąc find . -name my-search-term -prune -exec sh -c 'find "$0" … -exec … "{"} +' {} \; np. Za pomocą "{"}, w który zamieni się powłoka {}. … (Ciąg dalszy)
Scott
6

- gołe rozwiązania -

Jeśli chcesz findpominąć zawartość znalezionego katalogu, ale kontynuować wyszukiwanie w innych katalogach, użyj -prunejako sugerowanego @laebshade. Pełne polecenie powinno wtedy wyglądać

 find . -type d -name somename -prune -exec ...

Z drugiej strony, jeśli chcesz find, aby całkowicie zatrzymać wyszukiwanie i po znalezieniu pierwszego pasującego katalogu, to co szukasz jest -quit(dostępny od wersji 4.2.3z GNU find). Ten jest nieco trudniejszy w użyciu, ponieważ powoduje findnatychmiastowe wyjście - dlatego -quitnależy go umieścić na samym końcu polecenia:

find . -type d -name somename -exec ... -quit

Aby działało to zgodnie z oczekiwaniami, należy upewnić się, że -execzwracane są wartości true (innymi słowy, zero ). Jeśli chcesz, aby status wyjścia -execbył ignorowany, aby -quitzawsze działało, potrzebujesz małej sztuczki:

find . -type d -name somename \( -exec ... -o -true \) -quit

lub

find . -type d -name somename \( -exec ... -o -quit \)

lub

find . -type d -name somename \( -exec ... , -quit \) # a comma before -quit

- jakieś wyjaśnienie -

Najważniejsze w tym, jak finddziała, jest to, że wszystkie działania („testy”) są traktowane jako logiczne predykaty interpretowane od lewej do prawej. Dlatego ostatnia akcja (na przykład -quit) zostanie wykonana tylko wtedy, gdy cała poprzednia część nie zwróci wartości false . Domyślnie wszystkie testy są połączone logicznym „ORAZ”, -oopcja zmienia połączenie na „LUB”.

Trudnym elementem -ojest to, że findmoże „zoptymalizować” twoje polecenie i nie uruchamiać -execczęści, jeśli tylko wpiszesz

find . -type d -name somename -exec ... -o -quit

Aby sobie z tym poradzić, możesz zmusić finddo oceny wszystkich predykatów powiązanych z „LUB”, umieszczając je w nawiasach.

rozcietrzewiacz
źródło