Chcę znaleźć pliki, które kończą się na _peaks.bed
, ale wykluczyć pliki w folderach tmp
i scripts
.
Moje polecenie jest takie:
find . -type f \( -name "*_peaks.bed" ! -name "*tmp*" ! -name "*scripts*" \)
Ale to nie zadziałało. Pliki w tmp
i script
nadal będą wyświetlane folderu.
Czy ktoś ma jakieś pomysły na ten temat?
_peaks.bed
.find
, ale ponieważ pytanie jest oznaczone jako Linux, nie stanowi to problemu. Dobra odpowiedź..
podczas początkowego monitu o wyszukiwanie, musisz użyć go w każdej wykluczonej ścieżce. Dopasowanie ścieżki jest dość ścisłe, nie wykonuje wyszukiwania rozmytego. Więc jeśli używasz,find / -type f -name *.bed" ! -path "./tmp/"
to nie zadziała. musisz! -path "/tmp"
to uszczęśliwić.$ ! -path "./directory/*"
-prune
zamiast sprawdzania każdego pliku w drzewie." Jeśli wykluczone katalogi działają bardzo głęboko lub mają mnóstwo plików i zależy Ci na wydajności, użyj-prune
zamiast tego opcji.Oto jeden sposób, w jaki możesz to zrobić ...
find . -type f -name "*_peaks.bed" | egrep -v "^(./tmp/|./scripts/)"
źródło
find
, a nie tylko z GNUfind
. Jednak pytanie jest oznaczone jako Linux, więc nie jest krytyczne.Posługiwać się
find \( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -print
lub
find \( -path "./tmp" -o -path "./scripts" \) -prune -false -o -name "*_peaks.bed"
lub
find \( -path "./tmp" -path "./scripts" \) ! -prune -o -name "*_peaks.bed"
Kolejność jest ważna. Ocenia od lewej do prawej. Zawsze zaczynaj od wykluczenia ścieżki.
Wyjaśnienie
Nie używaj
-not
(lub!
) do wykluczania całego katalogu. Użyj-prune
. Jak wyjaśniono w instrukcji:oraz w podręczniku GNU znajdź:
Rzeczywiście, jeśli użyjesz
-not -path "./pathname"
, find oceni wyrażenie dla każdego węzła pod"./pathname"
.wyrażenia find to tylko ocena warunków.
\( \)
- obsługa grup (możesz użyć-path "./tmp" -prune -o -path "./scripts" -prune -o
, ale jest bardziej rozwlekła).-path "./script" -prune
- jeśli-path
zwraca prawdę i jest katalogiem, zwraca prawdę dla tego katalogu, a nie schodzi do niego.-path "./script" ! -prune
- ocenia jako(-path "./script") AND (! -prune)
. Przywraca „zawsze prawdę” śliwki na zawsze fałszywą. Unika drukowania"./script"
jako dopasowania.-path "./script" -prune -false
- ponieważ-prune
zawsze zwraca true, możesz wykonać to-false
samo, co!
.-o
- operator OR. Jeśli żaden operator nie jest określony między dwoma wyrażeniami, domyślnie używany jest operator AND.W związku z tym
\( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -print
jest rozszerzany do:[ (-path "./tmp" OR -path "./script") AND -prune ] OR ( -name "*_peaks.bed" AND print )
Nadruk jest tutaj ważny, ponieważ bez niego jest rozszerzany do:
{ [ (-path "./tmp" OR -path "./script" ) AND -prune ] OR (-name "*_peaks.bed" ) } AND print
-print
jest dodawany przez find - dlatego przez większość czasu nie trzeba go dodawać w swoim wyrażeniu. I od tego czasu-prune
zwraca prawdę, wypisze "./script" i "./tmp".W innych nie jest to konieczne, ponieważ się zmieniliśmy
-prune
aby zawsze zwracać fałsz.Wskazówka: możesz użyć,
find -D opt expr 2>&1 1>/dev/null
aby zobaczyć, jak jest zoptymalizowany i rozwinięty,find -D search expr 2>&1 1>/dev/null
aby zobaczyć, która ścieżka jest zaznaczona.źródło
Spróbuj czegoś takiego
find . \( -type f -name \*_peaks.bed -print \) -or \( -type d -and \( -name tmp -or -name scripts \) -and -prune \)
i nie zdziw się, jeśli trochę się pomyliłem. Jeśli celem jest exec (zamiast print), po prostu zastąp go w miejscu.
źródło
dla mnie to rozwiązanie nie działało na poleceniu exec z find, naprawdę nie wiem dlaczego, więc moje rozwiązanie jest
find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \;
Wyjaśnienie: samo co sampson-chen z dodatkami
-prune - zignoruj ścieżkę proceduralną ...
-o - Następnie, jeśli brak dopasowania, wydrukuj wyniki (wyczyść katalogi i wydrukuj pozostałe wyniki)
18:12 $ mkdir a b c d e 18:13 $ touch a/1 b/2 c/3 d/4 e/5 e/a e/b 18:13 $ find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \; gzip: . is a directory -- ignored gzip: ./a is a directory -- ignored gzip: ./b is a directory -- ignored gzip: ./c is a directory -- ignored ./c/3: 0.0% -- replaced with ./c/3.gz gzip: ./d is a directory -- ignored ./d/4: 0.0% -- replaced with ./d/4.gz gzip: ./e is a directory -- ignored ./e/5: 0.0% -- replaced with ./e/5.gz ./e/a: 0.0% -- replaced with ./e/a.gz ./e/b: 0.0% -- replaced with ./e/b.gz
źródło
find . -path ./scripts -prune -name '*_peaks.bed' -type f
. Nie wiem, jak wykluczyć wiele katalogów. Wyświetla również wykluczony katalog najwyższego poziomu, mimo żetype
został określony. Wykluczanie przez Grepa wydaje się prostsze, chyba że chcesz użyć śliwki, aby przyspieszyć operację wyszukiwania.Możesz spróbować poniżej:
find ./ ! \( -path ./tmp -prune \) ! \( -path ./scripts -prune \) -type f -name '*_peaks.bed'
źródło