Mylę -prune
się, że jest to działanie (jak -print
), a nie test (jak -name
). Zmienia listę „czynności do wykonania”, ale zawsze zwraca wartość true .
Ogólny wzór użycia -prune
jest następujący:
find [path] [conditions to prune] -prune -o \
[your usual conditions] [actions to perform]
Prawie zawsze chcesz -o
(logiczne OR) natychmiast po tym -prune
, ponieważ ta pierwsza część testu (do włącznie -prune
) zwróci false dla rzeczy, których naprawdę chcesz (tj. Rzeczy, których nie chcesz przycinać).
Oto przykład:
find . -name .snapshot -prune -o -name '*.foo' -print
Znajduje to pliki „* .foo”, które nie znajdują się w katalogach „.snapshot”. W tym przykładzie -name .snapshot
składa się [conditions to prune]
, i -name '*.foo' -print
jest [your usual conditions]
i [actions to perform]
.
Ważne uwagi :
Jeśli wszystko, co chcesz zrobić, to wydrukować wyniki, które możesz wykorzystać do pominięcia -print
akcji. Zasadniczo nie chcesz tego robić podczas używania -prune
.
Domyślne zachowanie find to „i” całe wyrażenie wraz z -print
akcją, jeśli -prune
na końcu nie ma żadnych akcji innych niż (ironicznie). Oznacza to, że napisanie tego:
find . -name .snapshot -prune -o -name '*.foo' # DON'T DO THIS
jest równoznaczne z napisaniem tego:
find . \( -name .snapshot -prune -o -name '*.foo' \) -print # DON'T DO THIS
co oznacza, że wypisze również nazwę katalogu, który przycinasz, co zwykle nie jest tym, czego chcesz. Zamiast tego lepiej jest wyraźnie określić -print
akcję, jeśli tego właśnie chcesz:
find . -name .snapshot -prune -o -name '*.foo' -print # DO THIS
Jeśli zdarzy się, że „zwykły warunek” pasuje do plików, które również pasują do stanu suszonych śliwek, pliki te nie zostaną uwzględnione w wynikach. Aby to naprawić, dodaj -type d
predykat do stanu śliwek.
Załóżmy na przykład, że chcemy wyciąć każdy katalog, który zaczynał się .git
(co jest wprawdzie nieco wymyślone - zwykle wystarczy usunąć dokładnie taką nazwę .git
), ale poza tym chciałem zobaczyć wszystkie pliki, w tym pliki podobne .gitignore
. Możesz spróbować tego:
find . -name '.git*' -prune -o -type f -print # DON'T DO THIS
Nie byłoby to uwzględnione .gitignore
w danych wyjściowych. Oto poprawiona wersja:
find . -name '.git*' -type d -prune -o -type f -print # DO THIS
Dodatkowa wskazówka: jeśli używasz wersji GNU find
, strona texinfo dla find
zawiera bardziej szczegółowe wyjaśnienie niż strona podręcznika (tak jak w przypadku większości narzędzi GNU).
Laurence Gonsalves
źródło
-prune
nie działa tylko na katalogach (ale w przypadku katalogów zapobiega także wprowadzaniu katalogów spełniających ten warunek, tj. tutaj katalogów spełniających ten warunek-name .snapshot
).-prune
na marginesie, to nie jest tak naprawdę przyczyną. Problem polega na tym, że „zwarcia” operatora lub mają niższy priorytet niż i. Rezultat końcowy jest taki, że jeśli.snapshot
napotkany plik zostanie napotkany, będzie pasował do pierwszego-name
,-prune
a następnie nie zrobi nic (tylko zwróci true), a następnie znak „ or” zwróci true, ponieważ jego lewy argument był prawdziwy. Akcja (np .-print
:) jest częścią drugiego argumentu, więc nigdy nie ma szansy na wykonanie.-print
na końcu, mogę teraz przestać dodawać\! -path <pattern>
oprócz-prune
Zwykle natywny sposób, w jaki robimy rzeczy w systemie Linux, i sposób myślenia od lewej do prawej.
Więc najpierw napisz, czego szukasz:
Następnie prawdopodobnie naciskasz klawisz Enter i zdajesz sobie sprawę, że otrzymujesz zbyt wiele plików z katalogów, których nie chcesz. Wykluczmy / media, aby uniknąć przeszukiwania zamontowanych dysków.
Teraz powinieneś DODATKOWAĆ następujące polecenie do poprzedniego polecenia:
więc końcowe polecenie to:
............... | <--- Uwzględnij ---> | .................... | <- -------- Wyklucz ---------> |
Myślę, że ta struktura jest znacznie łatwiejsza i koreluje z właściwym podejściem
źródło
find
jest wystarczająco sprytny, aby-prune
najpierw przetworzyć klauzulę. Hmmm, ciekawe.-prune
od teraz./media
, zauważając, że nie jest wywoływany,*.php
a następnie sprawdzam, czy jest on w środku/media
, widząc, że tak, i dlatego pomijam całe to poddrzewo. Nadal jest od lewej do prawej, nie robi żadnej różnicy, o ile obie kontrole się nie pokrywają.Uważaj, że -prune nie zapobiega schodzeniu do żadnego katalogu, jak niektórzy powiedzieli. Zapobiega zejściu do katalogów pasujących do testu, do którego jest zastosowany. Być może niektóre przykłady pomogą (zobacz przykład wyrażenia regularnego na dole). Przepraszam, że to jest tak długie.
źródło
find . -name test -prune -o -print
: iow,-prune
jest to akcja, która również działa na plikachDodanie do porady podanej w innych odpowiedziach (nie mam przedstawiciela do tworzenia odpowiedzi) ...
W przypadku łączenia
-prune
z innymi wyrażeniami istnieje subtelna różnica w zachowaniu w zależności od tego, które inne wyrażenia są używane.Przykład @Laurence Gonsalves znajdzie pliki „* .foo”, które nie znajdują się w katalogach „.snapshot”: -
Jednak ten nieco inny skrót, być może niechcący, wyświetli również
.snapshot
katalog (i wszystkie zagnieżdżone katalogi .snapshot): -Powodem jest (według strony podręcznika w moim systemie):
Oznacza to, że drugi przykład jest równoważny wpisaniu następującego, modyfikując w ten sposób grupę terminów:
Widać to przynajmniej w Solarisie 5.10. Używając różnych smaków * nix przez około 10 lat, dopiero niedawno szukałem powodu, dla którego tak się dzieje.
źródło
-prune
zi bez-print
!Przycinanie to polecenie „nie powtarzaj” przy żadnym przełączniku katalogu.
Ze strony podręcznika
Zasadniczo nie będzie odkładał się do żadnych podkatalogów.
Weź ten przykład:
Masz następujące katalogi
Jeśli uruchomisz
find -name test2
:Zwróci oba katalogi
Jeśli uruchomisz
find -name test2 -prune
:Zwróci tylko / home / test2, ponieważ nie zejdzie do / home / test2, aby znaleźć / home / test2 / test2
źródło
Nie jestem w tym ekspertem (a ta strona była bardzo pomocna wraz z http://mywiki.wooledge.org/UsingFind )
Właśnie zauważyłem,
-path
że ścieżka, która w pełni pasuje do ciągu / ścieżki, która pojawia się tuż pofind
(.
w tych przykładach), gdzie as-name
pasuje do wszystkich basename.blokuje katalog .git w twoim bieżącym katalogu ( jak się znajdujesz w
.
)blokuje rekursywnie wszystkie podkatalogi .git.
Zauważ, że
./
jest to niezwykle ważne !!-path
musi pasować do ścieżki zakotwiczonej.
lub cokolwiek nadejdzie zaraz po znalezieniu, jeśli trafisz bez niej (z drugiej strony lub „-o
”), prawdopodobnie prawdopodobnie nie jest przycinany! Byłem naiwnie tego nieświadomy i to zmusiło mnie do użycia opcji -path, gdy jest to świetne, gdy nie chcesz przycinać wszystkich podkatalogów o tej samej nazwie basename: Dźródło
find bla/
, to potrzebujesz -pathbla/
.git (lub*
zamiast tego popchnąłbyś z przodu a zachowałby się bardziej jak -name)Pokaż wszystko, w tym sam reż, ale nie jego nudną zawartość:
źródło
Jeśli przeczytasz tutaj wszystkie dobre odpowiedzi, rozumiem teraz, że następujące wyniki zwracają te same wyniki:
Ale ostatni zajmie dużo więcej czasu, ponieważ wciąż szuka wszystkiego w reż1. Myślę, że prawdziwym pytaniem jest, jak
-or
wyeliminować niepożądane wyniki bez ich przeszukiwania.Więc wydaje mi się, że suszona śliwka oznacza nie przyzwoite wcześniejsze mecze, ale oznaczam to jako zrobione ...
http://www.gnu.org/software/findutils/manual/html_mono/find.html „Nie dzieje się tak jednak ze względu na efekt działania„ -prune ”(który tylko zapobiega dalszemu zejściu, nie upewnia się ignorujemy ten element). Zamiast tego efekt ten wynika z użycia „-o”. Ponieważ warunek „lub” po lewej stronie się powiódł ./src/emacs, nie jest konieczne ocenianie prawej- hand-side („-print”) w ogóle dla tego konkretnego pliku. ”
źródło
find
buduje listę plików. Stosuje predykat podany dla każdego z nich i zwraca te, które przejdą.Ten pomysł
-prune
oznaczający wykluczenie z wyników był dla mnie bardzo mylący. Możesz wykluczyć plik bez przycinania:Wszystko
-prune
to zmienia zachowanie wyszukiwania. Jeśli bieżącym dopasowaniem jest katalog, jest napisane „hejfind
, właśnie dopasowany plik, nie schodź do niego” . Po prostu usuwa to drzewo (ale nie sam plik) z listy plików do przeszukania.To powinno być nazwane
-dont-descend
.źródło
Istnieje wiele odpowiedzi; niektóre z nich są trochę zbyt ciężkie w teorii. Zostawię, dlaczego raz potrzebowałem śliwek, więc może wyjaśnienie typu potrzeba / przykład jest komuś przydatne :)
Problem
Miałem folder z około 20 katalogami węzłów, z których każdy miał swój
node_modules
katalog zgodnie z oczekiwaniami.Po wejściu do dowolnego projektu zobaczysz każdy
../node_modules/module
. Ale wiesz jak to jest. Prawie każdy moduł ma zależności, więc to, na co patrzysz, bardziej przypominaprojectN/node_modules/moduleX/node_modules/moduleZ...
Nie chciałem utopić się z listą zależną od zależności ...
Znając
-d n
/-depth n
, to by mi nie pomogło, ponieważ katalog główny / pierwszy węzeł_modules, którego chciałem dla każdego projektu, był na innej głębokości, na przykład:Jak mogę uzyskać pierwszą listę ścieżek kończących się na pierwszej
node_modules
i przejść do następnego projektu, aby uzyskać to samo?Wchodzić
-prune
Po dodaniu
-prune
nadal będziesz mieć standardowe wyszukiwanie rekurencyjne. Każda „ścieżka” jest analizowana, a każde znalezisko wypluwa się ifind
kopie jak dobry facet. Ale to jest szukanienode_modules
czegoś więcej, czego nie chciałem.Tak, różnica jest taka, że w każdym z tych różnych ścieżek,
-prune
będziefind
przestać kopać dalej w tym konkretnym alei kiedy znalazła swój przedmiot. W moim przypadkunode_modules
folder.źródło