Bul komutunu kullanın, ancak iki dizindeki dosyaları hariç tutun


88

_peaks.bedİle biten dosyaları bulmak , ancak tmpve scriptsklasörlerindeki dosyaları dışlamak istiyorum .

Benim emrim şöyle:

 find . -type f \( -name "*_peaks.bed" ! -name "*tmp*" ! -name "*scripts*" \)

Ama işe yaramadı. tmpVe scriptklasöründeki dosyalar yine de görüntülenecektir.

Bunun hakkında fikri olan var mı?

Yanıtlar:


192

Bunu şu şekilde belirtebilirsiniz find:

find . -type f -name "*_peaks.bed" ! -path "./tmp/*" ! -path "./scripts/*"

Açıklama:

  • find . - Bulmaya mevcut çalışma dizininden başlayın (varsayılan olarak özyinelemeli)
  • -type f - Belirtin find Yalnızca sonuçlarda dosya istediğinizi
  • -name "*_peaks.bed" - ile biten dosyaları arayın _peaks.bed
  • ! -path "./tmp/*" - Yolu ile başlayan tüm sonuçları hariç tut ./tmp/
  • ! -path "./scripts/*" - Yolu ile başlayan tüm sonuçları da hariç tut ./scripts/

Çözümü Test Etme:

$ mkdir a b c d e
$ touch a/1 b/2 c/3 d/4 e/5 e/a e/b
$ find . -type f ! -path "./a/*" ! -path "./b/*"

./d/4
./c/3
./e/a
./e/b
./e/5

Oldukça -nameyakındınız, seçenek yalnızca temel adını dikkate alır, burada -pathtüm yol dikkate alınır =)


İyi iş. Ancak, OP'nin istediği şeylerden birini, biten dosyaları bulmayı unuttunuz _peaks.bed.
alex

2
Bu, GNU'da bir dizi uzantı kullanır find, ancak soru Linux olarak etiketlendiğinden, bu bir sorun değildir. İyi cevap.
Jonathan Leffler

1
Kısa bir not: .İlk bul isteminizde kullanırsanız, bunu hariç tuttuğunuz her yolda kullanmanız gerekir. Yol eşleştirme oldukça katıdır, bulanık arama yapmaz. Yani kullanırsanız find / -type f -name *.bed" ! -path "./tmp/"işe yaramayacaktır. ! -path "/tmp"onu mutlu etmek zorundasın .
peelman

3
* İşaretinin önemli olduğuna dikkat etmek önemlidir. $ ! -path "./directory/*"
Thomas Bennett

3
Man sayfalarına göre: "Bir dizin ağacının tamamını yok saymak için -prune, ağaçtaki her dosyayı kontrol etmek yerine kullanın ." Dışarıda bıraktığınız dizinler çok derin çalışıyorsa veya tonlarca dosya içeriyorsa ve performansı önemsiyorsanız, -prunebunun yerine seçeneği kullanın.
thdoan

8

İşte bunu yapmanın bir yolu ...

find . -type f -name "*_peaks.bed" | egrep -v "^(./tmp/|./scripts/)"

2
Bu, findyalnızca GNU ile çalışmak yerine, herhangi bir sürümüyle çalışma avantajına sahiptir find. Ancak soru Linux olarak etiketlendiğinden bu kritik değildir.
Jonathan Leffler

2

Kullanım

find \( -path "./tmp" -o -path "./scripts" \) -prune -o  -name "*_peaks.bed" -print

veya

find \( -path "./tmp" -o -path "./scripts" \) -prune -false -o  -name "*_peaks.bed"

veya

find \( -path "./tmp" -path "./scripts" \) ! -prune -o  -name "*_peaks.bed"

Sıra önemlidir. Soldan sağa doğru değerlendirir. Her zaman yol dışlama ile başlayın.

Açıklama

Tüm dizini dışarıda bırakmak için -not(veya !) kullanmayın . Kullanın -prune. Kılavuzda açıklandığı gibi:

−prune    The primary shall always evaluate as  true;  it
          shall  cause  find  not  to descend the current
          pathname if it is a directory.  If  the  −depth
          primary  is specified, the −prune primary shall
          have no effect.

ve GNU'da kılavuzu bulun:

-path pattern
              [...]
              To ignore  a  whole
              directory  tree,  use  -prune rather than checking
              every file in the tree.

Aslında, kullanırsanız -not -path "./pathname", bul, altındaki her düğüm için ifadeyi değerlendirecektir."./pathname" .

bulma ifadeleri sadece koşul değerlendirmesidir.

  • \( \)- grupların çalışması (kullanabilirsiniz -path "./tmp" -prune -o -path "./scripts" -prune -o, ancak daha ayrıntılıdır).
  • -path "./script" -prune- eğer -pathgerçek döner ve bir dizin, yani dizin için gerçek dönmek ve do not içine inerler.
  • -path "./script" ! -prune- olarak değerlendirir (-path "./script") AND (! -prune). Bu erik "her zaman doğru" yu daima yanlışa döndürür. Yazdırmayı önler"./script" .
  • -path "./script" -prune -false- -pruneher zaman doğru döndüğünden -false, aynısını yapmak için takip edebilirsiniz! .
  • -o- VEYA operatörü. İki ifade arasında hiçbir operatör belirtilmezse, varsayılan olarak AND işlecidir.

Bu nedenle, \( -path "./tmp" -o -path "./scripts" \) -prune -o -name "*_peaks.bed" -printşu şekilde genişletilir:

[ (-path "./tmp" OR -path "./script") AND -prune ] OR ( -name "*_peaks.bed" AND print )

Baskı burada önemlidir çünkü o olmadan şu şekilde genişletilir:

{ [ (-path "./tmp" OR -path "./script" )  AND -prune ]  OR (-name "*_peaks.bed" ) } AND print

-printbul ile eklenir - bu nedenle çoğu zaman ifadenize eklemeniz gerekmez. Dan beri-prune true döndürdüğünden, "./script" ve "./tmp" yazacaktır.

Diğerlerinde gerekli değil çünkü değiştirdik -prune her zaman yanlış döndürmeye .

İpucu: Hangi yolun kontrol edildiğini find -D opt expr 2>&1 1>/dev/nullgörmek için nasıl optimize edildiğini ve genişletildiğini görmek için kullanabilirsiniz
find -D search expr 2>&1 1>/dev/null.


0

Gibi bir şey dene

find . \( -type f -name \*_peaks.bed -print \) -or \( -type d -and \( -name tmp -or -name scripts \) -and -prune \)

ve biraz yanlış anladıysam çok şaşırma. Hedef bir exec ise (baskı yerine), yerine koyun.


0

benim için bu çözüm find ile bir komut exec üzerinde çalışmadı, nedenini gerçekten bilmiyorum, bu yüzden benim çözümüm

find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \;

Açıklama: sampson-chen one ile aynı

-prune - prosedür yolunu yoksay ...

-o - Eşleşme yoksa sonuçları yazdır, (dizinleri budayın ve kalan sonuçları yazdırın)

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

Kabul edilen cevap işe yaramadı, ancak bu işe yarıyor. Kuru erik kullanarak find . -path ./scripts -prune -name '*_peaks.bed' -type f,. Birden çok dizini nasıl dışlayacağınızdan emin değilim. Bu ayrıca typebelirtilmiş olsa bile en üst düzey dışlanan dizini listeler . Bulma işlemini hızlandırmak için erik kullanmak istemediğiniz sürece Grep aracılığıyla hariç tutmak daha kolay görünüyor.
Mohnish

Birden fazla dizini dışlamakta da sorun yaşadım, ancak yukarıdaki yorumlar bana işe yarayan bir cevap verdi. Birden çok '-yol değil' örneği kullanıyorum ve her bir yol ifadesinde, her birini bir yıldız işaretiyle 'bulmak' ve sonlandırmak (ve herhangi bir noktadan kaçınmak) için ilk parametrede kullanılan tam öneki ekliyorum.
jet,

0

Aşağıdakileri deneyebilirsiniz:

find ./ ! \( -path ./tmp -prune \) ! \( -path ./scripts -prune \) -type f -name '*_peaks.bed'

2
Bunun gibi eski bir soru üzerine (4 yıl!) Bu yeni cevabın neden daha iyi veya farklı olduğunu açıklamak istersiniz, sadece "dökümü" kodu değil.
Nic3500
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.