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.