2014-04-21 25 views
23

belirli bir düzenle eşleşen tüm dosyaları bulmak:Recursively bu kalıpla eşleşen tüm dosyaları bulmak (veya daha spesifik olarak saymak) gerek

*/foo/* doc

Nerede birinci Joker yıldız değişken sayıda alt dizin içerir.

+1

Bash olmak zorunda mı? zsh, 'ls **/foo/*. doc' adlı sözdizimini kullanarak bunu yapabilir. – Alastair

+0

Alastair, öneri için teşekkürler. Zsh ve çift-asterik sözdiziminin farkında değildim. İlginç olarak, sonuçta ortaya çıkan argüman listesinin ls (yaklaşık 6000 dosya adı) için çok uzun olduğu ve bir hata verdiğini görüyoruz. – pw222

+0

Bash v4 ayrıca “**” özyineli globunu da destekler. – tripleee

cevap

27

sen (-name aksine) tüm yolu eşleşmesi normal ifadeler kullanabilirsiniz bulmak find dosya adı yerine inode numarasını yazdırmak için, dosya adından farklı olarak inode numarası bir satırsonu gibi karakterlere sahip olmadığından garantilidir, bu nedenle sayma daha güvenilirdir.Teklif için @tripleee'ye teşekkürler.

Bunun OSX üzerinde çalışıp çalışmayacağını bilmiyorum.

+2

Bunun sonuna "| wc -l" ekleyin ve mükemmel. – pw222

8

nasıl:

find BASE_OF_SEARCH/*/foo -name \*.doc -type f | wc -l

Bu ne yapıyor: dizin BASE_OF_SEARCH de

  • başlangıç ​​/ Bir dizin, foo dosyaları için
  • göz bütün dizinlerde
  • göz gibi adlandırılan * .doc
  • Sonuç (dosya başına bir)

Bu yöntemin faydası f: Bir senaryoya eklerseniz

  • değil özyinelemeli ne de yinelemeli (hayır döngüler)
  • okumak kolaydır ve deşifre etmek oldukça kolaydır (bazen ifade yoktur).

UPDATE: değişken derinlik ister misiniz? Tamam: * .doc

  • sadece "foo"
  • dahil bu sonucun çizgilerini göstermek gibi adlı dosyaları dizin BASE_OF_SEARCH de

    • başlangıç ​​

      find BASE_OF_SEARCH -name \*.doc -type f | grep foo | wc -l

    • görünüm satırları saymak Sonuç (dosya başına bir)

    İsteğe bağlı olarak, dosyada "foo" yazan sonuçları filtreleyebilirsiniz. isim, çünkü bunlar da gösterecek.

  • +0

    Bu, BASE_OF_SEARCH ve foo arasındaki değişken alt dizin derinliği ile çalışmadığı durumlar dışında çalışır. Belki de bu şartnameyle yeterince açık değildim. Yaptığım görevi yerine getirebildiğim için yeterince yakınım, bu yüzden bir bağış ve teşekkür ederim. – pw222

    +0

    Yinelemeli olmadığını vurgulamalıdır. Ancak, bu genellikle gerekli değildir. O zaman bu bir simpe ve hoş bir çözümdür. Performans sorunları olsa da - bilmiyorum. – robsch

    +0

    İsteklerinize bir özellik ekledim – MonkeyWidget

    2

    Untested, ancak deneyin:

    find . -type d -name foo -print | while read d; do echo "$d/*.doc" ; done | wc -l 
    

    (değişen derinliklerde) Tüm "foo" dizinleri bulmak (bu sembolik yok sayar, bu şekilde ekleyebilirsiniz sorunun bir parçası ise); Tüm ".doc" dosyalarını bulmak için kabuk globbing kullanın, sonra onları sayın.

    find . -regex '.*/foo/[^/]*.doc' -printf '%i\n' | wc -l 
    

    (%i biçim kodu nedenler:

    find . -regex '.*/foo/[^/]*.doc' 
    

    sadece dosya sayısını saymak için: GNU'da ile

    +0

    'while' döngüsü tamamen gereksiz ve biraz hataya eğilimlidir. Ayrıca, alıntı yapıldığı için joker karakteri genişletilmez. Sadece "bul -print" yi "wc -l" ye çevir. Ancak, bir dosya adı bir satırsonu içeriyorsa, bu yanlış sayımı yine de verecektir. – tripleee