Lepiej jest użyć find ... | while read -r file .... Ponadto lepiej jest akceptować i głosować odpowiedzi.
Wstrzymano do odwołania.
podczas gdy czytanie jest powolne, ponieważ
wejście
18
@mpapis podczas odczytu poprawnie obsługuje pełne linie ze spacjami.
Jean-Philippe Pellet
1
Wystarczy uruchomić ten w folderze z plikami ze spacjami w ich nazwach: for file in $(find .); do echo "$file"; done. Nazwy ze spacjami są podzielone, czego nie chcemy.
Jean-Philippe Pellet,
Odpowiedzi:
1140
Użyj -pruneprzełącznika. Na przykład, jeśli chcesz wykluczyć misckatalog, po prostu dodaj -path ./misc -prune -odo polecenia find:
Tutaj wykluczamy dir1 , dir2 i dir3 , ponieważ w findwyrażeniach jest to działanie, które działa na podstawie kryteriów -path dir1 -o -path dir2 -o -path dir3(jeśli dir1 lub dir2 lub dir3 ), AND z type -d.
Hmm To też nie działa dla mnie, ponieważ będzie zawierać zignorowany katalog „./misc” w danych wyjściowych.
Theuni,
84
@Theuni Prawdopodobnie nie działało to dla ciebie, ponieważ nie dodałeś -print(ani żadnej innej akcji) wyraźnie później -name. W takim przypadku obie „strony” drukują na -okońcu, natomiast jeśli używasz -print, drukowana jest tylko ta strona.
Daniel C. Sobral
4
Z manpage: Because -delete implies -depth, you cannot usefully use -prune and -delete together.Jak mogę usunąć z find, jeśli chcę wykluczyć określone katalogi z usunięcia?
Jānis Elmeris,
15
Aby usunąć cały katalog się od wykorzystania wyników: find . -not -path "./.git*". Użycie ./dir*zamiast ./dir/*usuwa katalog oraz zawartość z danych wyjściowych.
micahblu
64
To pytanie i zamieszanie w odpowiedziach pokazują, jak źle interfejs użytkownika wyszukiwania odpowiada potrzebom ludzi.
Johannes Overmann,
1931
Jeśli -pruneto nie zadziała, spowoduje to:
find -name "*.js"-not -path "./directory/*"
Uwaga: wymaga przejścia przez wszystkie niechciane katalogi.
Jeden z komentarzy w zaakceptowanej odpowiedzi wskazuje na problem. -prunenie wyklucza samego katalogu, wyklucza jego zawartość, co oznacza, że dostaniesz niechcianą linię na wyjściu z wykluczonym katalogiem.
GetFree
95
Świetna odpowiedź. Dodam do tego, że można wykluczyć katalog na DOWOLNYM poziomie, zmieniając pierwszy .na *. więc find -name "*.js" -not -path "*/omitme/*"pomijałby pliki z katalogu o nazwie „omitme” na dowolnym poziomie głębokości.
DeeDee
83
To wciąż przemierza cały niechcianego katalogu, choć. Dodaję własną odpowiedź. :-)
Daniel C. Sobral
18
Pamiętaj jednak, że opcja przycinania nie działa tylko wtedy, gdy nie używasz jej -printjawnie.
Daniel C. Sobral
39
Lepiej byłoby powiedzieć „Jest to alternatywa dla użycia -prune”. Odpowiedzi sugerujące, że śliwka nie są błędne, po prostu nie są takie, jak byś to zrobił.
Jimbo,
458
Uważam, że łatwiej jest uzasadnić niż inne proponowane rozwiązania:
Ważna uwaga: ścieżki, które wpisujesz, -pathmuszą dokładnie pasować do tego find, co zostanie wydrukowane bez wykluczenia. Jeśli to zdanie myli po prostu upewnij się, aby korzystać z pełnej ścieżki przechodzące przez całą polecenia jak poniżej: . Zobacz notatkę [1], jeśli chcesz lepiej zrozumieć.find /full/path/ -not \( -path /full/path/exclude/this -prune \) ...
Wewnątrz \(i \)jest wyrażeniem, które będą pasować dokładniebuild/external (patrz Ważna uwaga powyżej), i będzie, w przypadku sukcesu, unikać postępowy cokolwiek poniżej . Jest to następnie grupowane jako pojedyncze wyrażenie z nawiasem ucieczkowym i poprzedzone nim, -notco spowoduje findpominięcie wszystkiego, co pasowało do tego wyrażenia.
Można zapytać, czy dodanie -notnie spowoduje, że wszystkie inne pliki zostaną ukryte przez -pruneponowne pojawienie się, a odpowiedź brzmi „nie”. Sposób, w jaki -prunedziała to, że coś, że po jego osiągnięciu, pliki poniżej tego katalogu są stale ignorowane.
Wynika to z rzeczywistego przypadku użycia, w którym musiałem wywołać kompresor Yui w przypadku niektórych plików generowanych przez wintersmith, ale pomijać inne pliki, które należy przesłać w obecnej postaci.
Uwaga [1] : Jeśli chcesz wykluczyć /tmp/foo/bari uruchomisz wyszukiwanie w ten sposób find /tmp \(..., musisz to określić -path /tmp/foo/bar. Jeśli z drugiej strony tak się cd /tmp; find . \(...dzieje, musisz to określić -path ./foo/bar.
Znakomita odpowiedź, dziękuję. To działa i jest skalowalne (czytelne) dla wielu wykluczeń. Jesteś panem i panem uczonym. Dziękuję za przykład wielu wykluczeń
Freedom_Ben
7
To nie działa, jeśli chcę użyć przełącznika -delete:find . -not \( -path ./CVS -prune \) -type f -mtime +100 -delete find: The -delete action atomatically turns on -depth, but -prune does nothing when -depth is in effect. If you want to carry on anyway, just explicitly use the -depth option.
Analizując wyniki find, jest to naprawdę oczywiste, ale mnie to zaskoczyło. Jeśli szukasz w bieżącym katalogu (podając .jako ścieżkę wyszukiwania lub nie podając go wcale), najprawdopodobniej chcesz, aby wzorzec -pathzaczął od ./, np find -not \( -path ./.git -prune \) -type f. :
Zantier
7
Bardziej precyzyjna (i kompatybilna z POSIX) odmiana tej metody: find searchdir \! \( -type d \( -path './excludedir/*' -o -path './excludedir2/*' -o -path './excludedir3/*' \) -prune \)po której następują wszelkie warunki, które powinny pasować do tego, czego szukasz.
Walf
217
Widać tutaj pewne zamieszanie co do preferowanej składni do pomijania katalogu.
Opinia GNU
To ignore a directory and the files under it, use -prune
-pruneprzestaje findschodzić do katalogu. Samo określenie -not -pathnadal będzie przechodzić do pominiętego katalogu, ale -not -pathbędzie fałszywe przy każdym findtestowaniu każdego pliku.
Problemy z -prune
-prune robi to, do czego jest przeznaczony, ale nadal są pewne rzeczy, o które musisz zadbać, używając go.
find drukuje przycięty katalog.
PRAWDA To zamierzone zachowanie, po prostu się do niego nie schodzi. Aby całkowicie nie wydrukować katalogu, użyj składni, która logicznie go pomija.
-prunedziała tylko -printbez żadnych innych działań.
NIE PRAWDA . -prunewspółpracuje z dowolną akcją oprócz -delete. Dlaczego to nie działa z usuwaniem? Aby -deletedziałać, find musi przechodzić przez katalog w kolejności DFS, ponieważ -deletenajpierw usunie liście, następnie rodziców liści itp. Ale aby określić, -pruneże ma to sens, findmusi trafić do katalogu i przestać go opuszczać, co wyraźnie nie ma sensu z włączaniem -depthlub -deletewyłączaniem.
Wydajność
Przygotowałem prosty test z trzema najwyżej ocenionymi odpowiedziami na to pytanie (zastąpione -printprzez, -exec bash -c 'echo $0' {} \;aby pokazać inny przykład działania). Wyniki są poniżej
----------------------------------------------# of files/dirs in level one directories.performance_test/prune_me 702702.performance_test/other 2----------------------------------------------> find ".performance_test"-path ".performance_test/prune_me"-prune -o -exec bash -c 'echo "$0"'{} \;
.performance_test
.performance_test/other
.performance_test/other/foo
[# of files]3[Runtime(ns)]23513814> find ".performance_test"-not \( -path ".performance_test/prune_me"-prune \) -exec bash -c 'echo "$0"'{} \;
.performance_test
.performance_test/other
.performance_test/other/foo
[# of files]3[Runtime(ns)]10670141> find ".performance_test"-not -path ".performance_test/prune_me*"-exec bash -c 'echo "$0"'{} \;
.performance_test
.performance_test/other
.performance_test/other/foo
[# of files]3[Runtime(ns)]864843145
Wniosek
Zarówno składnia f10bit, jak i składnia Daniela C. Sobrala trwały średnio 10–25 ms. Składnia GetFree , która nie korzysta -prune, zajęła 865 ms. Tak, jest to raczej skrajny przykład, ale jeśli zależy ci na czasie działania i robisz coś zdalnie intensywnego, powinieneś użyć -prune.
Uwaga : składnia Daniela C. Sobrala była lepsza z dwóch -prune; ale mocno podejrzewam, że jest to wynikiem pewnego buforowania, ponieważ zmiana kolejności, w której oba działały, dawała przeciwny wynik, podczas gdy wersja bez przycinania była zawsze najwolniejsza.
Dziękuję za bardzo dobrą analizę. Jeśli chodzi o „mocno podejrzewam, że jest to wynikiem pewnego buforowania”, możesz uruchomić następującą komendę: sudo sh -c „free && sync && echo 3> / proc / sys / vm / drop_caches && free”, aby wyczyścić pamięć podręczną (patrz unix. stackexchange.com/questions/87908/… ).
ndemou
Po kilku testach na tych dwóch ze -prunestwierdzam, że rzadko jest jakakolwiek różnica. Czy należy pamiętać, że polecenie rozpoczęcia który pierwszy skorzystają z wydajności procesora, później cpu rozgrzać> spadek wydajności przyczyna moll spowolnienie (zrobiłem oczyszczania pamięci podręcznej przed każdym poleceniu jako @ndemou sugestią)
Huy.PhamNhu
Spróbuj zmienić numer name1() name2() name3()w powyższym skrypcie testowym @BroSlow, aby zmienić kolejność wykonywania, aby uzyskać obraz tego, co powiedziałem. W prawdziwym życiu między nimi jest jednak niezauważalne.
Huy.PhamNhu
Oklaski. Dziękuję za tę wysokiej jakości odpowiedź.
Stphane
Nie powinieneś być -o co oznacza lub. więc przycinasz w pierwszym kroku, a potem zapominasz o tym w następnym.
mmm
94
To jedyny, który dla mnie działał.
find /-name MyFile!-path '*/Directory/*'
Wyszukiwanie „MyFile” z wyłączeniem „Directory”. Podkreśl gwiazdy *.
Spowoduje to, że twoje wyszukiwanie będzie bardzo wolne
Dorian
6
Ten działał dla mnie, inne (które wykorzystują -prune) - nie.
Andron
7
Powolny w dużych wynikach, ale przydatny w mniejszych zestawach. Ale jak wykluczyć wiele katalogów za pomocą grep? Oczywiście w ten sposób: find . -name '*.js' | grep -v excludeddir | grep -v excludedir2 | grep -v excludedir3ale może istnieć jeden sposób grep.
Timo Kähkönen
6
Jeśli chcesz wykonywać wiele greps wtedy można byłoby lepiej pisanie go jako wyrażenia regularne: egrep -v '(dir1|dir2|dir3)'. Jednak w tym konkretnym studium przypadku lepiej byłoby wykluczyć katalogi wewnątrz findsiebie.
Laurence
1
tak, nie potrzebujesz nawiasów i lepiej użyć ^, aby upewnić się, że pasuje do nazwy katalogu na początku ciągu, np .: find. -nazwa „* .js” | egrep -v "^ \ ./ wykluczyć katalog1 | ^ \ ./ wykluczyć katalog2"
To jedyne rozwiązanie typu „znajdź”, które działało dla mnie. Katalogi, które chciałem wykluczyć, NIE znajdują się bezpośrednio poniżej bieżącego katalogu roboczego.
Lambart
5
Jednak dodanie -printdo końca może poprawić wyniki. find . -type d -name .hg -prune -o -name datazignorowano zawartość (wielu) .hgkatalogów, ale wymieniono .hgsame katalogi. W -printliście wymieniono tylko te katalogi „danych”, których szukałem.
Lambart,
19
-prunezdecydowanie działa i jest najlepszą odpowiedzią, ponieważ zapobiega zejściu do katalogu, który chcesz wykluczyć. -not -pathktóry nadal przeszukuje wykluczony katalog, po prostu nie drukuje wyniku, co może być problemem, jeśli wyłączonym katalogiem jest podłączony wolumin sieciowy lub użytkownik nie ma uprawnień.
Część trudna polega na tym, że findjest bardzo szczególna w kolejności argumentów, więc jeśli nie zrozumiesz ich poprawnie, twoje polecenie może nie działać. Kolejność argumentów jest na ogół taka:
find {path}{options}{action}
{path}: Najpierw umieść wszystkie argumenty związane ze ścieżką, np . -path './dir1' -prune -o
{options}: Odnoszę największy sukces, gdy stawiam -name, -iname, etcjako ostatnią opcję w tej grupie. Na przykład-type f -iname '*.js'
{action}: Będziesz chciał dodać -printpodczas korzystania-prune
Oto działający przykład:
# setup test
mkdir dir1 dir2 dir3
touch dir1/file.txt; touch dir1/file.js
touch dir2/file.txt; touch dir2/file.js
touch dir3/file.txt; touch dir3/file.js
# search for *.js, exclude dir1
find .-path './dir1'-prune -o -type f -iname '*.js'-print
# search for *.js, exclude dir1 and dir2
find . \( -path './dir1'-o -path './dir2' \) -prune -o -type f -iname '*.js'-print
Próbowałem tego i nadal schodzi do katalogów, więc prędkość zdecydowanie nie jest poprawiona.
Br.Bill
10
Podejście -path -prune działa również z symbolami wieloznacznymi na ścieżce. Oto instrukcja find, która znajdzie katalogi dla serwera git obsługującego wiele repozytoriów git z pominięciem wewnętrznych katalogów git:
Jest wiele dobrych odpowiedzi, zajęło mi trochę czasu, aby zrozumieć, do czego służy każdy element polecenia i jaka jest logika.
find .-path ./misc -prune -o -name '*.txt'-print
find rozpocznie wyszukiwanie plików i katalogów w bieżącym katalogu, stąd find ..
-oOpcja oznacza logiczną OR i oddziela dwie części komendy:
[-path ./misc -prune ] OR [-name '*.txt'-print ]
Każdy katalog lub plik, który nie jest katalogiem ./misc, nie przejdzie pierwszego testu -path ./misc. Ale zostaną przetestowane pod kątem drugiego wyrażenia. Jeśli ich nazwa odpowiada wzorowi *.txt, drukowane są z powodu -printopcji.
Gdy find osiągnie katalog ./misc, katalog ten spełnia tylko pierwsze wyrażenie. Tak więc -pruneopcja zostanie zastosowana do niego. Mówi poleceniu find, aby nie eksplorowało tego katalogu. Tak więc żaden plik lub katalog w ./misc nie będzie nawet eksplorowany przez find, nie będzie testowany względem drugiej części wyrażenia i nie zostanie wydrukowany.
Każdy ma rozwiązanie, ale twoje najlepiej to wyjaśniło. Byłem nieugięty, żeby najpierw używać -name zamiast -path. Twoje wyjaśnienie było odpowiednie, aby dojść do tego, czego chciałem. odnaleźć . -nazwa „* .txt” -print -o -path ./misc -prune
Vendetta V
7
Dla działającego rozwiązania (testowane na Ubuntu 12.04 (Precise Pangolin)) ...
find !-path "dir1"-iname "*.mp3"
wyszuka pliki MP3 w bieżącym folderze i podfolderach, z wyjątkiem podfolderu dir1.
Nie działa dla mnie. Nie wykonuj też żadnej z powyższych odpowiedzi. Czerwony kapelusz.
Tharpa
6
dobrą sztuczką pozwalającą uniknąć drukowania przyciętych katalogów jest użycie -print(działa -execrównież) po prawej stronie -orpo -prune. Na przykład, ...
find .-path "*/.*"-prune -or -iname "*.j2"
wydrukuje ścieżkę wszystkich plików w bieżącym katalogu z rozszerzeniem `.j2", pomijając wszystkie ukryte katalogi. Schludnie. Ale wydrukuje również wydruk pełną ścieżkę każdego katalogu, który pomija, jak wspomniano powyżej. Jednak następujące nie, ...
find .-path "*/.*"-prune -or -iname "*.j2"-print
ponieważ logicznie jest ukryte -andza -inameoperatorem i przed nadrukiem. To wiąże go z prawą częścią -orzdania ze względu na logiczną kolejność operacji i asocjatywność. Ale doktorzy mówią, że jest ukryty, -printjeśli on (lub którykolwiek z jego kuzynów ... -print0itd.) Nie jest określony. Dlaczego więc nie lewa część -orwydruku? Najwyraźniej (i nie zrozumiałem tego po pierwszym przeczytaniu strony podręcznika), to prawda, jeśli nie ma nic, tylko operatory opisowe najwyraźniej nic nie zrobiłyby, więc myślę, że ma to sens. Jak wspomniano powyżej, to wszystko również działa , więc poniższe zawiera pełną listę każdego pliku z pożądanym rozszerzeniem, ale nie wyświetla pierwszego poziomu każdego ukrytego katalogu, ...-print operacji w stylu -lub wyrażonej w dowolnej klauzuli, wszystkie te ukryte logiczne znikają i dostajesz tylko to, co ty sprecyzować. Szczerze mówiąc, wolałbym to na odwrót, ale potem-exec gdziekolwiek, w którym to przypadku, -print jest logicznie traktowane wokół tak, że wszystko zostanie wydrukowany. Jeśli nawet JEDENprintfind-execls -la
find .-path "*/.*"-prune -or -iname "*.j2"-exec ls -la --{}+
Dla mnie (i innych w tym wątku) findskładnia robi się dość barokowa dość szybko, więc zawsze rzucam pareny, aby upewnić się, że wiem, co się z tym wiąże, więc zwykle tworzę makro dla zdolności pisania i formuję wszystkie takie stwierdzenia jak. ..
find . \( \( ... description of stuff to avoid ... \) -prune \) -or \
\( ... description of stuff I want to find ...[-exec or -print] \)
Trudno się pomylić, ustanawiając świat na dwie części w ten sposób. Mam nadzieję, że to pomaga, choć wydaje się mało prawdopodobne, aby ktokolwiek przeczytał ponad 30. odpowiedź i zagłosował, ale można mieć nadzieję. :-)
Rozwiązanie grep jest jedynym, które wyklucza wszystkie katalogi o tej samej nazwie. Przy próbie wykluczenia „node_modules” jest to całkiem przydatne.
bmacnaughton
3
@bmacnaughton - nieprawda! Przybyłem tu specjalnie po to, aby wykluczyć „node_modules” i po przeczytaniu wielu dobrych odpowiedzi zdecydowałem się na find . -type f -print -o -path "*/node_modules" -prune... używając znaku wieloznacznego pomija „node_modules” na dowolnym poziomie; użycie -printpierwszej alternatywy -type f -printpowoduje wydrukowanie tylko tej części, więc same katalogi „node_modules” nie są wymienione. (może być również odwrotna: find . -path "*/node_modules" -prune -o -type f -print)
Stephen P
co * tam robi. Jaki dokładnie plik chcesz wykluczyć. Czy używasz go jako symbolu wieloznacznego?
Siju V
1
@StephenP, dzięki za zwrócenie na to uwagi; Nauczyłem się różnicy między używaniem ./node_modulesa */node_modulestym. W moim przypadku, node_modulesgdy istnieje tylko w katalogu, w którym rozpoczynam wyszukiwanie (i w tym node_moduleskatalogu), mogę użyć, find . -type f -print -o -path "./node_modules" -prune ponieważ nie będzie node_moduleskatalogu w żadnym innym katalogu.
bmacnaughton
1
@SijuV - w katalogu, w którym szukałem, był node_modulespodkatalog, ale były też podkatalogi, które miały swoje własne moduły_węzłów ... używając ./node_modulesdopasowań tylko podkatalogu node_modulesw bieżącym katalogu .i przycinają go; używając */node_modulesdopasowuje i przycina katalog na dowolnej głębokości, ponieważ *jako glob pasuje do dowolnego wiodącego prefiksu ścieżki, takiego jak ./test5/main/node_modulesnie tylko ./prefiks. *Jest wieloznaczny, ale jako glob nie jako regex.
Nie mogę tego zrobić. find ~/Projects -name '*.js' -\! -name 'node_modules' -prunewciąż wyświetla pliki node_modulesna swojej ścieżce
mpen
1
@mpen, Od stackoverflow.com/questions/4210042/… , dowiedziałem się, że potrzebna jest składnia find ~/Projects -path ~/Projects/node_modules -prune -o -name '*.js' -print. Nazwa tej ścieżki musi dokładnie pasować do tego, co znajdzie, co wydrukowałoby, gdyby miał wydrukować katalog.
TLDR: zrozum katalogi główne i dostosuj wyszukiwanie z tego miejsca, korzystając z tej -path <excluded_path> -prune -oopcji. Nie dołączaj końcowego/ końca na końcu wykluczonej ścieżki.
Aby skutecznie korzystać z find, uważam, że konieczne jest dobre zrozumienie struktury katalogów systemu plików. Na moim komputerze domowym mam dyski twarde o pojemności TB, z kopią zapasową około połowy tej zawartości przy użyciu rsnapshot(tj rsync.). Chociaż tworzy kopię zapasową na fizycznie niezależnym (zduplikowanym) dysku, jest on montowany w katalogu systemowym root ( /) /mnt/Backups/rsnapshot_backups/:
/mnt/Backups/rsnapshot_backups/Katalog zajmuje obecnie ~ 2,9 TB, z ~ 60m plików i folderów; po prostu przeglądanie tych treści wymaga czasu:
## As sudo (#), to avoid numerous "Permission denied" warnings:
time find /mnt/Backups/rsnapshot_backups | wc -l
60314138## 60.3M files, folders34:07.30## 34 min
time du /mnt/Backups/rsnapshot_backups -d 03112240160/mnt/Backups/rsnapshot_backups ## 3.1 TB33:51.88## 34 min
time rsnapshot du ## << more accurate re: rsnapshot footprint2.9T/mnt/Backups/rsnapshot_backups/hourly.0/4.1G/mnt/Backups/rsnapshot_backups/hourly.1/...4.7G/mnt/Backups/rsnapshot_backups/weekly.3/2.9T total ## 2.9 TB, per sudo rsnapshot du (more accurate)2:34:54## 2 hr 35 min
Dlatego za każdym razem, gdy muszę wyszukać plik na mojej /(głównej) partycji, muszę poradzić sobie (jeśli to możliwe) przechodząc przez moją partycję kopii zapasowych.
PRZYKŁADY
Wśród podejść, które są różnie sugerowane w tym wątku ( Jak wykluczyć katalog w poleceniu find. ), Stwierdzam, że wyszukiwania przy użyciu zaakceptowanej odpowiedzi są znacznie szybsze - z zastrzeżeniami.
Rozwiązanie 1
Powiedzmy, że chcę znaleźć plik systemowy libname-server-2.a, ale nie chcę przeszukiwać rsnapshotkopii zapasowych. Aby szybko znaleźć plik systemowy, użyj wykluczyć ścieżkę /mnt(czyli zastosowanie /mnt, nie /mnt/, albo /mnt/Backups, albo ...):
## As sudo (#), to avoid numerous "Permission denied" warnings:
time find /-path /mnt -prune -o -name "*libname-server-2.a*"-print
/usr/lib/libname-server-2.a
real 0m8.644s## 8.6 sec <<< NOTE!
user 0m1.669s
sys 0m2.466s## As regular user (victoria); I also use an alternate timing mechanism, as## here I am using 2>/dev/null to suppress "Permission denied" warnings:
$ START="$(date +"%s")"&& find 2>/dev/null /-path /mnt -prune -o \
-name "*libname-server-2.a*"-print; END="$(date +"%s")"; \
TIME="$((END - START))"; printf 'find command took %s sec\n'"$TIME"/usr/lib/libname-server-2.a
find command took 3 sec ## ~3 sec <<< NOTE!
... znajduje ten plik w ciągu kilku sekund, a to trwa znacznie dłużej (wydaje się, że powtarza się we wszystkich „wykluczonych” katalogach):
## As sudo (#), to avoid numerous "Permission denied" warnings:
time find /-path /mnt/-prune -o -name "*libname-server-2.a*"-print
find: warning:-path /mnt/ will not match anything because it ends with /./usr/lib/libname-server-2.a
real 33m10.658s## 33 min 11 sec (~231-663x slower!)
user 1m43.142s
sys 2m22.666s## As regular user (victoria); I also use an alternate timing mechanism, as## here I am using 2>/dev/null to suppress "Permission denied" warnings:
$ START="$(date +"%s")"&& find 2>/dev/null /-path /mnt/-prune -o \
-name "*libname-server-2.a*"-print; END="$(date +"%s")"; \
TIME="$((END - START))"; printf 'find command took %s sec\n'"$TIME"/usr/lib/libname-server-2.a
find command took 1775 sec ## 29.6 min
Rozwiązanie 2
Inne rozwiązanie oferowane w tym wątku ( SO # 4210042 ) również działa słabo:
## As sudo (#), to avoid numerous "Permission denied" warnings:
time find /-name "*libname-server-2.a*"-not -path "/mnt"/usr/lib/libname-server-2.a
real 33m37.911s## 33 min 38 sec (~235x slower)
user 1m45.134s
sys 2m31.846s
time find /-name "*libname-server-2.a*"-not -path "/mnt/*"/usr/lib/libname-server-2.a
real 33m11.208s## 33 min 11 sec
user 1m22.185s
sys 2m29.962s
PODSUMOWANIE | WNIOSKI
Zastosuj podejście przedstawione w „ Rozwiązaniu 1 ”
zauważając, że za każdym razem, gdy dodajesz znak końcowy /do wykluczonej ścieżki, findpolecenie rekurencyjnie wchodzi (wszystkie te) /mnt/*katalogi - które w moim przypadku, z powodu /mnt/Backups/rsnapshot_backups/*podkatalogów, zawierają dodatkowo ~ 2,9 TB plików do przeszukania! Nie dołączając znaku /końca, wyszukiwanie powinno zakończyć się niemal natychmiast (w ciągu kilku sekund).
... -not -path <exclude path> ...Wydaje się, że „Rozwiązanie 2” ( ) rekurencyjnie przeszukuje wykluczone katalogi - nie zwraca wykluczonych dopasowań, ale niepotrzebnie pochłania ten czas wyszukiwania.
Wyszukiwanie w ramach tych rsnapshotkopii zapasowych:
Aby znaleźć plik w jednej z moich godzinnych / dziennych / tygodniowych / miesięcznych rsnapshotkopii zapasowych):
$ START="$(date +"%s")"&& find 2>/dev/null /mnt/Backups/rsnapshot_backups/daily.0-name '*04t8ugijrlkj.jpg'; END="$(date +"%s")"; TIME="$((END - START))"; printf 'find command took %s sec\n'"$TIME"/mnt/Backups/rsnapshot_backups/daily.0/snapshot_root/mnt/Vancouver/temp/04t8ugijrlkj.jpg
find command took 312 sec ## 5.2 minutes: despite apparent rsnapshot size## (~4 GB), it is in fact searching through ~2.9 TB)
Z wyłączeniem zagnieżdżonego katalogu:
Tutaj chcę wykluczyć katalog zagnieżdżony, np. /mnt/Vancouver/projects/ie/claws/data/*Podczas wyszukiwania z /mnt/Vancouver/projects/:
$ time find .-iname '*test_file*'./ie/claws/data/test_file
./ie/claws/test_file
0:01.97
$ time find .-path '*/data'-prune -o -iname '*test_file*'-print
./ie/claws/test_file
0:00.07
Na bok: Dodanie -printna końcu polecenia pomija wydruk wykluczonego katalogu:
To nie wielkość plików spowalnia find, to liczba pozycji katalogu, które musi zbadać. Jest więc znacznie gorzej, jeśli masz wiele, wiele małych plików (zwłaszcza jeśli wszystkie są wielokrotnie połączone!) Niż jeśli masz tylko garść plików o pojemności wielu gigabajtów.
Toby Speight
@TobySpeight: dobry punkt. Wspomniałem o wielkości przestrzeni wyszukiwania, aby wskazać skalę, która zawiera również wiele plików. Szybkie wyszukiwanie katalogu głównego (/) sudo ls -R / | wc -lwskazuje ~ 76,5 mln plików (większość z nich jest archiwizowana, z wyjątkiem plików systemowych innych niż config); /mnt/Vancouver/z ls -R | wc -loznacza ~ 2,35 mln plików; /home/victoria/zawiera pliki 0.668M.
Victoria Stuart,
4
Możesz także użyć wyrażeń regularnych, aby włączyć / wyłączyć niektóre pliki / katalogi wyszukiwania, używając czegoś takiego:
Użyłem, findaby dostarczyć listę plików xgettexti chciałem pominąć konkretny katalog i jego zawartość. Próbowałem wielu -pathkombinacji w połączeniu z, -pruneale nie byłem w stanie w pełni wykluczyć katalogu, który chciałem zniknąć.
Chociaż byłem w stanie zignorować zawartość katalogu, który chciałem zignorować, zwróciłem findsam katalog jako jeden z wyników, co spowodowałoxgettext awarię w wyniku (nie akceptuje katalogów, tylko pliki).
Moim rozwiązaniem było po prostu grep -vpominięcie katalogu, którego nie chciałem w wynikach:
Bez względu na to, czy istnieje argument przemawiający za findtym, czy będzie on działał w 100%, nie mogę powiedzieć na pewno. Korzystanie grepbyło szybkim i łatwym rozwiązaniem po pewnym bólu głowy.
Nie widzę powodu, dla którego żadna z odpowiedzi z więcej niż 100 punktami nie powinna działać na Ubuntu.
Axel Beckert
mmm, zobaczmy? może dlatego, że wypróbowałem je wszystkie?
Sixro
find jest wszędzie tą samą implementacją we wszystkich dystrybucjach Linuksa - tą z Projektu GNU. Jedyną różnicą mogą być wersje. Ale zmiany w ostatniej dekadzie nie były tak inwazyjne, z wyjątkiem może dopasowania uprawnień.
Z stackoverflow.com/questions/4210042 /... dowiedziałem się, że składnia użyta dla parametru -pathmust pasuje do znalezionej nazwy, która zostałaby wydrukowana, gdyby wydrukowała katalog, na przykład find . -path ./.git -prune -o -print, lub find $HOME/foo -path $HOME/foo/.git -prune -o -print niektóre odpowiedzi po prostu mówią, -path somedirktóra niestety jest niewystarczająco dokładne, aby były przydatne.
PatS
2
Dla tego, czego potrzebowałem, działało to tak: znajdowanie landscape.jpgna wszystkich serwerach zaczynających się od katalogu głównego i wykluczanie wyszukiwania w /varkatalogu:
Znalazłem nazwę funkcji w plikach źródłowych C wykluczających * .o i wykluczających * .swp i wykluczających (nie zwykły plik) i wykluczających dane wyjściowe katalogu za pomocą tego polecenia:
find . \( !-path "./output/*" \) -a \( -type f \) -a \( !-name '*.o' \) -a \( !-name '*.swp' \) | xargs grep -n soc_attach
Bardzo stare pytanie, ale wciąż jest miejsce na ulepszenia. Znalazłem to przypadkiem, próbując rozwiązać podobny problem i żadna z odpowiedzi nie była zadowalająca.
Alberto,
execCzęsto używam tej akcji i uważam ją za bardzo przydatną. Zazwyczaj dodaję cudzysłowy, {}jeśli w ścieżkach plików są spacje, co daje "{}".
Ludovic Kuty,
@lkuty Miałem właśnie edytować mój post, aby odzwierciedlić twój komentarz, ale po szybkim teście (bez cytowania {}działa w przypadku plików z białymi spacjami w nazwach) i przejrzeniu stron podręcznika, wydaje się, że cytowanie jest konieczne, aby uniknąć są błędnie interpretowane jako interpunkcja skryptu powłoki. W takim przypadku użyłbyś pojedynczego cudzysłowu:'{}'
Alberto
Myślę, że musiałem go użyć do zrobienia cplub mvlub rm. Sprawdzę to
Ludovic Kuty
1
Próbowałem polecenia powyżej, ale żaden z tych, którzy używają „-prune” nie działa dla mnie. W końcu wypróbowałem to za pomocą poniższego polecenia:
find . \( -name "*" \) -prune -a !-name "directory"
find ... | while read -r file ...
. Ponadto lepiej jest akceptować i głosować odpowiedzi.for file in $(find .); do echo "$file"; done
. Nazwy ze spacjami są podzielone, czego nie chcemy.Odpowiedzi:
Użyj
-prune
przełącznika. Na przykład, jeśli chcesz wykluczyćmisc
katalog, po prostu dodaj-path ./misc -prune -o
do polecenia find:Oto przykład z wieloma katalogami:
Tutaj wykluczamy dir1 , dir2 i dir3 , ponieważ w
find
wyrażeniach jest to działanie, które działa na podstawie kryteriów-path dir1 -o -path dir2 -o -path dir3
(jeśli dir1 lub dir2 lub dir3 ), AND ztype -d
.Dalsze działanie to
-o print
po prostu wydrukuj.źródło
-print
(ani żadnej innej akcji) wyraźnie później-name
. W takim przypadku obie „strony” drukują na-o
końcu, natomiast jeśli używasz-print
, drukowana jest tylko ta strona.Because -delete implies -depth, you cannot usefully use -prune and -delete together.
Jak mogę usunąć z find, jeśli chcę wykluczyć określone katalogi z usunięcia?find . -not -path "./.git*"
. Użycie./dir*
zamiast./dir/*
usuwa katalog oraz zawartość z danych wyjściowych.Jeśli
-prune
to nie zadziała, spowoduje to:Uwaga: wymaga przejścia przez wszystkie niechciane katalogi.
źródło
-prune
nie wyklucza samego katalogu, wyklucza jego zawartość, co oznacza, że dostaniesz niechcianą linię na wyjściu z wykluczonym katalogiem..
na*
. więcfind -name "*.js" -not -path "*/omitme/*"
pomijałby pliki z katalogu o nazwie „omitme” na dowolnym poziomie głębokości.-print
jawnie.Uważam, że łatwiej jest uzasadnić niż inne proponowane rozwiązania:
Ważna uwaga: ścieżki, które wpisujesz,
-path
muszą dokładnie pasować do tegofind
, co zostanie wydrukowane bez wykluczenia. Jeśli to zdanie myli po prostu upewnij się, aby korzystać z pełnej ścieżki przechodzące przez całą polecenia jak poniżej: . Zobacz notatkę [1], jeśli chcesz lepiej zrozumieć.find /full/path/ -not \( -path /full/path/exclude/this -prune \) ...
Wewnątrz
\(
i\)
jest wyrażeniem, które będą pasować dokładniebuild/external
(patrz Ważna uwaga powyżej), i będzie, w przypadku sukcesu, unikać postępowy cokolwiek poniżej . Jest to następnie grupowane jako pojedyncze wyrażenie z nawiasem ucieczkowym i poprzedzone nim,-not
co spowodujefind
pominięcie wszystkiego, co pasowało do tego wyrażenia.Można zapytać, czy dodanie
-not
nie spowoduje, że wszystkie inne pliki zostaną ukryte przez-prune
ponowne pojawienie się, a odpowiedź brzmi „nie”. Sposób, w jaki-prune
działa to, że coś, że po jego osiągnięciu, pliki poniżej tego katalogu są stale ignorowane.Wynika to z rzeczywistego przypadku użycia, w którym musiałem wywołać kompresor Yui w przypadku niektórych plików generowanych przez wintersmith, ale pomijać inne pliki, które należy przesłać w obecnej postaci.
Uwaga [1] : Jeśli chcesz wykluczyć
/tmp/foo/bar
i uruchomisz wyszukiwanie w ten sposóbfind /tmp \(...
, musisz to określić-path /tmp/foo/bar
. Jeśli z drugiej strony tak sięcd /tmp; find . \(...
dzieje, musisz to określić-path ./foo/bar
.źródło
find . -not \( -path ./CVS -prune \) -type f -mtime +100 -delete find: The -delete action atomatically turns on -depth, but -prune does nothing when -depth is in effect. If you want to carry on anyway, just explicitly use the -depth option.
-exec rm -rf {} \;
zamiast-delete
.find
, jest to naprawdę oczywiste, ale mnie to zaskoczyło. Jeśli szukasz w bieżącym katalogu (podając.
jako ścieżkę wyszukiwania lub nie podając go wcale), najprawdopodobniej chcesz, aby wzorzec-path
zaczął od./
, npfind -not \( -path ./.git -prune \) -type f
. :find searchdir \! \( -type d \( -path './excludedir/*' -o -path './excludedir2/*' -o -path './excludedir3/*' \) -prune \)
po której następują wszelkie warunki, które powinny pasować do tego, czego szukasz.Widać tutaj pewne zamieszanie co do preferowanej składni do pomijania katalogu.
Opinia GNU
Ze strony podręcznika użytkownika GNU znajdź
Rozumowanie
-prune
przestajefind
schodzić do katalogu. Samo określenie-not -path
nadal będzie przechodzić do pominiętego katalogu, ale-not -path
będzie fałszywe przy każdymfind
testowaniu każdego pliku.Problemy z
-prune
-prune
robi to, do czego jest przeznaczony, ale nadal są pewne rzeczy, o które musisz zadbać, używając go.find
drukuje przycięty katalog.-prune
działa tylko-print
bez żadnych innych działań.-prune
współpracuje z dowolną akcją oprócz-delete
. Dlaczego to nie działa z usuwaniem? Aby-delete
działać, find musi przechodzić przez katalog w kolejności DFS, ponieważ-delete
najpierw usunie liście, następnie rodziców liści itp. Ale aby określić,-prune
że ma to sens,find
musi trafić do katalogu i przestać go opuszczać, co wyraźnie nie ma sensu z włączaniem-depth
lub-delete
wyłączaniem.Wydajność
Przygotowałem prosty test z trzema najwyżej ocenionymi odpowiedziami na to pytanie (zastąpione
-print
przez,-exec bash -c 'echo $0' {} \;
aby pokazać inny przykład działania). Wyniki są poniżejWniosek
Zarówno składnia f10bit, jak i składnia Daniela C. Sobrala trwały średnio 10–25 ms. Składnia GetFree , która nie korzysta
-prune
, zajęła 865 ms. Tak, jest to raczej skrajny przykład, ale jeśli zależy ci na czasie działania i robisz coś zdalnie intensywnego, powinieneś użyć-prune
.Uwaga : składnia Daniela C. Sobrala była lepsza z dwóch
-prune
; ale mocno podejrzewam, że jest to wynikiem pewnego buforowania, ponieważ zmiana kolejności, w której oba działały, dawała przeciwny wynik, podczas gdy wersja bez przycinania była zawsze najwolniejsza.Skrypt testowy
źródło
-prune
stwierdzam, że rzadko jest jakakolwiek różnica. Czy należy pamiętać, że polecenie rozpoczęcia który pierwszy skorzystają z wydajności procesora, później cpu rozgrzać> spadek wydajności przyczyna moll spowolnienie (zrobiłem oczyszczania pamięci podręcznej przed każdym poleceniu jako @ndemou sugestią)name1() name2() name3()
w powyższym skrypcie testowym @BroSlow, aby zmienić kolejność wykonywania, aby uzyskać obraz tego, co powiedziałem. W prawdziwym życiu między nimi jest jednak niezauważalne.To jedyny, który dla mnie działał.
Wyszukiwanie „MyFile” z wyłączeniem „Directory”. Podkreśl gwiazdy *.
źródło
! -path '*/Directory/*'
do polecenia kolejno, aby zignorować wiele katalogówdocker container
jedynym współpracuje zsh -c "find..."
Jedną z opcji byłoby wykluczenie wszystkich wyników zawierających nazwę katalogu z grep. Na przykład:
źródło
-prune
) - nie.find . -name '*.js' | grep -v excludeddir | grep -v excludedir2 | grep -v excludedir3
ale może istnieć jeden sposób grep.egrep -v '(dir1|dir2|dir3)'
. Jednak w tym konkretnym studium przypadku lepiej byłoby wykluczyć katalogi wewnątrzfind
siebie.Wolę
-not
notację ... jest bardziej czytelna:źródło
find
podręcznika man mówi: „Aby zignorować katalog i znajdujące się pod nim pliki, użyj -prune”.find . -iname '*' -and -not -path './somePath'
nie uniemożliwia temu wejściu do wspomnianego katalogu.find . -iname '*' -not -path './.git/*'
find . -not -path "*/.git*"
byłoby to, czego chcesz.Użyj opcji -prune. Coś w stylu:
Opcja „-type d -name proc -prune” szuka tylko katalogów o nazwie proc, które mają zostać wykluczone.
„-O” jest operatorem „LUB”.
źródło
-print
do końca może poprawić wyniki.find . -type d -name .hg -prune -o -name data
zignorowano zawartość (wielu).hg
katalogów, ale wymieniono.hg
same katalogi. W-print
liście wymieniono tylko te katalogi „danych”, których szukałem.-prune
zdecydowanie działa i jest najlepszą odpowiedzią, ponieważ zapobiega zejściu do katalogu, który chcesz wykluczyć.-not -path
który nadal przeszukuje wykluczony katalog, po prostu nie drukuje wyniku, co może być problemem, jeśli wyłączonym katalogiem jest podłączony wolumin sieciowy lub użytkownik nie ma uprawnień.Część trudna polega na tym, że
find
jest bardzo szczególna w kolejności argumentów, więc jeśli nie zrozumiesz ich poprawnie, twoje polecenie może nie działać. Kolejność argumentów jest na ogół taka:{path}
: Najpierw umieść wszystkie argumenty związane ze ścieżką, np. -path './dir1' -prune -o
{options}
: Odnoszę największy sukces, gdy stawiam-name, -iname, etc
jako ostatnią opcję w tej grupie. Na przykład-type f -iname '*.js'
{action}
: Będziesz chciał dodać-print
podczas korzystania-prune
Oto działający przykład:
źródło
To jest format, którego użyłem do wykluczenia niektórych ścieżek:
Użyłem tego, aby znaleźć wszystkie pliki spoza ścieżek „. *”:
źródło
Podejście -path -prune działa również z symbolami wieloznacznymi na ścieżce. Oto instrukcja find, która znajdzie katalogi dla serwera git obsługującego wiele repozytoriów git z pominięciem wewnętrznych katalogów git:
źródło
Aby wykluczyć wiele katalogów:
Aby dodać katalogi, dodaj
-o -path "./dirname/*"
:Ale może powinieneś użyć wyrażenia regularnego , jeśli istnieje wiele katalogów do wykluczenia.
źródło
Jest wiele dobrych odpowiedzi, zajęło mi trochę czasu, aby zrozumieć, do czego służy każdy element polecenia i jaka jest logika.
find rozpocznie wyszukiwanie plików i katalogów w bieżącym katalogu, stąd
find .
.-o
Opcja oznacza logiczną OR i oddziela dwie części komendy:Każdy katalog lub plik, który nie jest katalogiem ./misc, nie przejdzie pierwszego testu
-path ./misc
. Ale zostaną przetestowane pod kątem drugiego wyrażenia. Jeśli ich nazwa odpowiada wzorowi*.txt
, drukowane są z powodu-print
opcji.Gdy find osiągnie katalog ./misc, katalog ten spełnia tylko pierwsze wyrażenie. Tak więc
-prune
opcja zostanie zastosowana do niego. Mówi poleceniu find, aby nie eksplorowało tego katalogu. Tak więc żaden plik lub katalog w ./misc nie będzie nawet eksplorowany przez find, nie będzie testowany względem drugiej części wyrażenia i nie zostanie wydrukowany.źródło
Dla działającego rozwiązania (testowane na Ubuntu 12.04 (Precise Pangolin)) ...
wyszuka pliki MP3 w bieżącym folderze i podfolderach, z wyjątkiem podfolderu dir1.
Posługiwać się:
... aby wykluczyć katalog 1 i katalog 2
źródło
dobrą sztuczką pozwalającą uniknąć drukowania przyciętych katalogów jest użycie
-print
(działa-exec
również) po prawej stronie-or
po-prune
. Na przykład, ...wydrukuje ścieżkę wszystkich plików w bieżącym katalogu z rozszerzeniem `.j2", pomijając wszystkie ukryte katalogi. Schludnie. Ale wydrukuje również wydruk pełną ścieżkę każdego katalogu, który pomija, jak wspomniano powyżej. Jednak następujące nie, ...
ponieważ logicznie jest ukryte
-and
za-iname
operatorem i przed nadrukiem. To wiąże go z prawą częścią-or
zdania ze względu na logiczną kolejność operacji i asocjatywność. Ale doktorzy mówią, że jest ukryty,-print
jeśli on (lub którykolwiek z jego kuzynów ...-print0
itd.) Nie jest określony. Dlaczego więc nie lewa część-or
wydruku? Najwyraźniej (i nie zrozumiałem tego po pierwszym przeczytaniu strony podręcznika), to prawda, jeśli nie ma nic, tylko operatory opisowe najwyraźniej nic nie zrobiłyby, więc myślę, że ma to sens. Jak wspomniano powyżej, to wszystko również działa , więc poniższe zawiera pełną listę każdego pliku z pożądanym rozszerzeniem, ale nie wyświetla pierwszego poziomu każdego ukrytego katalogu, ...-print
operacji w stylu -lub wyrażonej w dowolnej klauzuli, wszystkie te ukryte logiczne znikają i dostajesz tylko to, co ty sprecyzować. Szczerze mówiąc, wolałbym to na odwrót, ale potem-exec
gdziekolwiek, w którym to przypadku, -print jest logicznie traktowane wokół tak, że wszystko zostanie wydrukowany. Jeśli nawet JEDENprint
find
-exec
ls -la
Dla mnie (i innych w tym wątku)
find
składnia robi się dość barokowa dość szybko, więc zawsze rzucam pareny, aby upewnić się, że wiem, co się z tym wiąże, więc zwykle tworzę makro dla zdolności pisania i formuję wszystkie takie stwierdzenia jak. ..Trudno się pomylić, ustanawiając świat na dwie części w ten sposób. Mam nadzieję, że to pomaga, choć wydaje się mało prawdopodobne, aby ktokolwiek przeczytał ponad 30. odpowiedź i zagłosował, ale można mieć nadzieję. :-)
źródło
Aby to zrobić, możesz użyć opcji przycinania. Jak na przykład:
Lub odwrotna opcja grep „grep -v”:
Możesz znaleźć szczegółowe instrukcje i przykłady w Linuxie polecenie find wyklucza wyszukiwanie katalogów .
źródło
find . -type f -print -o -path "*/node_modules" -prune
... używając znaku wieloznacznego pomija „node_modules” na dowolnym poziomie; użycie-print
pierwszej alternatywy-type f -print
powoduje wydrukowanie tylko tej części, więc same katalogi „node_modules” nie są wymienione. (może być również odwrotna:find . -path "*/node_modules" -prune -o -type f -print
)./node_modules
a*/node_modules
tym. W moim przypadku,node_modules
gdy istnieje tylko w katalogu, w którym rozpoczynam wyszukiwanie (i w tymnode_modules
katalogu), mogę użyć,find . -type f -print -o -path "./node_modules" -prune
ponieważ nie będzienode_modules
katalogu w żadnym innym katalogu.node_modules
podkatalog, ale były też podkatalogi, które miały swoje własne moduły_węzłów ... używając./node_modules
dopasowań tylko podkatalogunode_modules
w bieżącym katalogu.
i przycinają go; używając*/node_modules
dopasowuje i przycina katalog na dowolnej głębokości, ponieważ*
jako glob pasuje do dowolnego wiodącego prefiksu ścieżki, takiego jak./test5/main/node_modules
nie tylko./
prefiks.*
Jest wieloznaczny, ale jako glob nie jako regex.źródło
find ~/Projects -name '*.js' -\! -name 'node_modules' -prune
wciąż wyświetla plikinode_modules
na swojej ścieżcefind ~/Projects -path ~/Projects/node_modules -prune -o -name '*.js' -print
. Nazwa tej ścieżki musi dokładnie pasować do tego, co znajdzie, co wydrukowałoby, gdyby miał wydrukować katalog.wydaje się działać tak samo jak
i łatwiej zapamiętać IMO.
źródło
TLDR: zrozum katalogi główne i dostosuj wyszukiwanie z tego miejsca, korzystając z tej
-path <excluded_path> -prune -o
opcji. Nie dołączaj końcowego/
końca na końcu wykluczonej ścieżki.Przykład:
find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
Aby skutecznie korzystać z
find
, uważam, że konieczne jest dobre zrozumienie struktury katalogów systemu plików. Na moim komputerze domowym mam dyski twarde o pojemności TB, z kopią zapasową około połowy tej zawartości przy użyciursnapshot
(tjrsync
.). Chociaż tworzy kopię zapasową na fizycznie niezależnym (zduplikowanym) dysku, jest on montowany w katalogu systemowym root (/
)/mnt/Backups/rsnapshot_backups/
:/mnt/Backups/rsnapshot_backups/
Katalog zajmuje obecnie ~ 2,9 TB, z ~ 60m plików i folderów; po prostu przeglądanie tych treści wymaga czasu:Dlatego za każdym razem, gdy muszę wyszukać plik na mojej
/
(głównej) partycji, muszę poradzić sobie (jeśli to możliwe) przechodząc przez moją partycję kopii zapasowych.PRZYKŁADY
Wśród podejść, które są różnie sugerowane w tym wątku ( Jak wykluczyć katalog w poleceniu find. ), Stwierdzam, że wyszukiwania przy użyciu zaakceptowanej odpowiedzi są znacznie szybsze - z zastrzeżeniami.
Rozwiązanie 1
Powiedzmy, że chcę znaleźć plik systemowy
libname-server-2.a
, ale nie chcę przeszukiwaćrsnapshot
kopii zapasowych. Aby szybko znaleźć plik systemowy, użyj wykluczyć ścieżkę/mnt
(czyli zastosowanie/mnt
, nie/mnt/
, albo/mnt/Backups
, albo ...):... znajduje ten plik w ciągu kilku sekund, a to trwa znacznie dłużej (wydaje się, że powtarza się we wszystkich „wykluczonych” katalogach):
Rozwiązanie 2
Inne rozwiązanie oferowane w tym wątku ( SO # 4210042 ) również działa słabo:
PODSUMOWANIE | WNIOSKI
Zastosuj podejście przedstawione w „ Rozwiązaniu 1 ”
to znaczy
zauważając, że za każdym razem, gdy dodajesz znak końcowy
/
do wykluczonej ścieżki,find
polecenie rekurencyjnie wchodzi (wszystkie te)/mnt/*
katalogi - które w moim przypadku, z powodu/mnt/Backups/rsnapshot_backups/*
podkatalogów, zawierają dodatkowo ~ 2,9 TB plików do przeszukania! Nie dołączając znaku/
końca, wyszukiwanie powinno zakończyć się niemal natychmiast (w ciągu kilku sekund).... -not -path <exclude path> ...
Wydaje się, że „Rozwiązanie 2” ( ) rekurencyjnie przeszukuje wykluczone katalogi - nie zwraca wykluczonych dopasowań, ale niepotrzebnie pochłania ten czas wyszukiwania.Wyszukiwanie w ramach tych
rsnapshot
kopii zapasowych:Aby znaleźć plik w jednej z moich godzinnych / dziennych / tygodniowych / miesięcznych
rsnapshot
kopii zapasowych):Z wyłączeniem zagnieżdżonego katalogu:
Tutaj chcę wykluczyć katalog zagnieżdżony, np.
/mnt/Vancouver/projects/ie/claws/data/*
Podczas wyszukiwania z/mnt/Vancouver/projects/
:Na bok: Dodanie
-print
na końcu polecenia pomija wydruk wykluczonego katalogu:źródło
find
, to liczba pozycji katalogu, które musi zbadać. Jest więc znacznie gorzej, jeśli masz wiele, wiele małych plików (zwłaszcza jeśli wszystkie są wielokrotnie połączone!) Niż jeśli masz tylko garść plików o pojemności wielu gigabajtów.sudo ls -R / | wc -l
wskazuje ~ 76,5 mln plików (większość z nich jest archiwizowana, z wyjątkiem plików systemowych innych niż config);/mnt/Vancouver/
zls -R | wc -l
oznacza ~ 2,35 mln plików;/home/victoria/
zawiera pliki 0.668M.Możesz także użyć wyrażeń regularnych, aby włączyć / wyłączyć niektóre pliki / katalogi wyszukiwania, używając czegoś takiego:
To da ci tylko wszystkie pliki js, vue, css itp., Ale z wyłączeniem wszystkich plików w folderach
node_modules
ivendor
.źródło
Użyłem,
find
aby dostarczyć listę plikówxgettext
i chciałem pominąć konkretny katalog i jego zawartość. Próbowałem wielu-path
kombinacji w połączeniu z,-prune
ale nie byłem w stanie w pełni wykluczyć katalogu, który chciałem zniknąć.Chociaż byłem w stanie zignorować zawartość katalogu, który chciałem zignorować, zwróciłem
find
sam katalog jako jeden z wyników, co spowodowałoxgettext
awarię w wyniku (nie akceptuje katalogów, tylko pliki).Moim rozwiązaniem było po prostu
grep -v
pominięcie katalogu, którego nie chciałem w wynikach:Bez względu na to, czy istnieje argument przemawiający za
find
tym, czy będzie on działał w 100%, nie mogę powiedzieć na pewno. Korzystaniegrep
było szybkim i łatwym rozwiązaniem po pewnym bólu głowy.źródło
Żadna z poprzednich odpowiedzi nie jest dobra na Ubuntu. Spróbuj tego:
Znalazłem to tutaj
źródło
Jest to odpowiednie dla mnie na komputerze Mac:
Wyklucza
vendor
iapp/cache
reżimem szukanej nazwy z przyrostkiemphp
.źródło
Dla tych z was w starszych wersjach UNIX, którzy nie mogą używać -path lub -not
Testowane na SunOS 5.10 bash 3.2 i SunOS 5.11 bash 4.4
źródło
how-to-use-prune-option-of-find-in-sh to doskonała odpowiedź Laurence Gonsalves na temat tego, jak
-prune
działa.A oto ogólne rozwiązanie:
Aby uniknąć
/path/to/seach/
wielokrotnego pisania , zawińfind
wpushd .. popd
parę.źródło
-path
must pasuje do znalezionej nazwy, która zostałaby wydrukowana, gdyby wydrukowała katalog, na przykładfind . -path ./.git -prune -o -print
, lubfind $HOME/foo -path $HOME/foo/.git -prune -o -print
niektóre odpowiedzi po prostu mówią,-path somedir
która niestety jest niewystarczająco dokładne, aby były przydatne.Dla tego, czego potrzebowałem, działało to tak: znajdowanie
landscape.jpg
na wszystkich serwerach zaczynających się od katalogu głównego i wykluczanie wyszukiwania w/var
katalogu:find / -maxdepth 1 -type d | grep -v /var | xargs -I '{}' find '{}' -name landscape.jpg
find / -maxdepth 1 -type d
wymienia wszystkie d irectories w/
grep -v /var
wyklucza `/ var 'z listyxargs -I '{}' find '{}' -name landscape.jpg
wykonaj dowolne polecenie, na przykładfind
dla każdego katalogu / wyniku z listyźródło
/
nie jest jeszcze wykluczone. Możesz potrzebowaćsed 1d
.Działa następujące polecenie:
Jeśli masz problem ze znalezieniem, użyj
-D tree
opcji, aby wyświetlić informacje analizy wyrażeń.Lub
-D all
, aby wyświetlić wszystkie informacje o wykonaniu.źródło
Znalazłem nazwę funkcji w plikach źródłowych C wykluczających * .o i wykluczających * .swp i wykluczających (nie zwykły plik) i wykluczających dane wyjściowe katalogu za pomocą tego polecenia:
źródło
Lepiej użyj
exec
akcji niżfor
pętli:exec ... '{}' ... '{}' \;
Będzie wykonywana raz dla każdego pliku pasującego, zastępując szelki'{}'
z aktualną nazwą pliku.Zauważ, że nawiasy klamrowe są ujęte w pojedyncze znaki cudzysłowu, aby chronić je przed interpretacją jako interpunkcji skryptu powłoki * .
Notatki
* W sekcji Przykłady
find (GNU findutils) 4.4.2
manualuźródło
exec
Często używam tej akcji i uważam ją za bardzo przydatną. Zazwyczaj dodaję cudzysłowy,{}
jeśli w ścieżkach plików są spacje, co daje"{}"
.{}
działa w przypadku plików z białymi spacjami w nazwach) i przejrzeniu stron podręcznika, wydaje się, że cytowanie jest konieczne, aby uniknąć są błędnie interpretowane jako interpunkcja skryptu powłoki. W takim przypadku użyłbyś pojedynczego cudzysłowu:'{}'
cp
lubmv
lubrm
. Sprawdzę toPróbowałem polecenia powyżej, ale żaden z tych, którzy używają „-prune” nie działa dla mnie. W końcu wypróbowałem to za pomocą poniższego polecenia:
źródło