Wyklucz podkatalog za pomocą funkcji find


115

Mam taką strukturę katalogów

data
|___
   |
   abc
    |____incoming
   def
    |____incoming
    |____processed
   123
    |___incoming
   456
    |___incoming
    |___processed

We wszystkich folderach w katalogu Data znajduje się przychodzący podfolder. Chcę pobrać wszystkie pliki ze wszystkich folderów i podfolderów z wyjątkiem katalogów def / incoming i 456 / incoming. Wypróbowałem za pomocą następującego polecenia

 find /home/feeds/data -type d \( -name 'def/incoming' -o -name '456/incoming' -o -name arkona \) -prune -o -name '*.*' -print

ale nie działa zgodnie z oczekiwaniami.

Ravi


3
To nie jest dobra rada, ale szybko i nieprzyjemnie wyciągnie cię z wielu sytuacji: odpuść to, grep -v somethingaby wykluczyć to, czego nie chcesz
— Miquel

Odpowiedzi:


206

To działa:

find /home/feeds/data -type f -not -path "*def/incoming*" -not -path "*456/incoming*"

Wyjaśnienie:

  • find /home/feeds/data: zacznij szukać rekurencyjnie od określonej ścieżki
  • -type f: znajdź tylko pliki
  • -not -path "*def/incoming*": nie uwzględniaj niczego def/incomingjako części swojej ścieżki
  • -not -path "*456/incoming*": nie uwzględniaj niczego 456/incomingjako części swojej ścieżki

otrzymywanie błędu „find: bad option -not find: path-list predicate-list”
— Ravi

@Ravi czy używasz powłoki bash? Właśnie przetestowałem to na moim terminalu i działa dla mnie. Spróbuj skopiować i wkleić rozwiązanie, jeśli wprowadziłeś modyfikacje w skrypcie.
— sampson-chen

Działa, ale wyświetla katalogi, a nie pliki w tych katalogach.
— Ravi

1
-pathpasuje do całego ciągu, więc jeśli robisz find ., twoje -pathstruny muszą być./path/to/directory/*
— Heath Borders

1
FYI na -not -pathpewno zadziała w tym przykładzie, ale findnadal iteruje w strukturze katalogów i używa cykli procesora do iteracji po wszystkich tych katalogach / plikach. aby zapobiec finditeracji po tych katalogach / plikach (być może są tam miliony plików), musisz użyć -prune( -pruneopcja jest jednak trudna w użyciu).
— Trevor Boyd Smith

9

Tylko ze względu na dokumentację: być może będziesz musiał kopać głębiej, ponieważ istnieje wiele konstelacji wyszukiwania i przeskakiwania (tak jak musiałem). Może się okazać, że pruneto twój przyjaciel, a -not -pathnie zrobi tego, czego oczekujesz.

Oto cenny przykład 15 przykładów wyszukiwania, które wykluczają katalogi:

http://www.theunixschool.com/2012/07/find-command-15-examples-to-exclude.html

Aby połączyć się z początkowym pytaniem, wykluczanie w końcu zadziałało dla mnie w ten sposób:

find . -regex-type posix-extended -regex ".*def/incoming.*|.*456/incoming.*" -prune -o -print 

Następnie, jeśli chcesz znaleźć jeden plik i nadal wykluczyć ścieżki, po prostu dodaj | grep myFile.txt.

Może to również zależeć od znalezionej wersji. Widzę:

$ find -version
GNU find version 4.2.27
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION SELINUX

5

-namepasuje tylko do nazwy pliku, a nie do całej ścieżki. Zamiast tego chcesz użyć -pathdla części, w których przycinasz katalogi, takie jak def/incoming.


2
find $(INP_PATH} -type f -ls |grep -v "${INP_PATH}/.*/"

7
Niektóre wyjaśnienia mogą sprawić, że będzie to znacznie lepsza odpowiedź.
— Cris Luengo,

Dziękujemy za ten fragment kodu, który może zapewnić ograniczoną krótkoterminową pomoc. Właściwe wyjaśnienie znacznie poprawiłoby jego długoterminową wartość, pokazując, dlaczego jest to dobre rozwiązanie problemu i uczyniłoby go bardziej użytecznym dla przyszłych czytelników z innymi, podobnymi pytaniami. Edytuj swoją odpowiedź, dodając wyjaśnienie, w tym przyjęte przez siebie założenia
— Shawn C.

1
Uwaga: ta sztuczka nie działa, jeśli używa się go find ... -print0w połączeniu z późniejszymxargs -0
— phs

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.