birden çok kalıpla eşleşen "find -name" kalıbı


335

Komut ile bir dizindeki tüm python ve html dosyalarının bir listesini almaya çalışıyordum find Documents -name "*.{py,html}".

Sonra adam sayfası geldi:

Desendeki ('{}') ayraçlar özel olarak kabul edilmez (yani. -Name 'foo {1,2}' bul foo1 ve foo2 dosyalarıyla değil, foo {1,2} adlı bir dosyayla eşleşir.

Bu bir boru zincirinin bir parçası olduğundan, çalışma zamanında hangi uzantılarla eşleştiğini (sabit kodlama yok) belirleyebilmek istiyorum. Eğer bulmayı başaramazsa, perl bir astar (veya benzeri) iyi olur.

Düzenleme: Sonunda geldi yanıtı bok her türlü içerir ve biraz da uzun, bu yüzden ben çizilmeye çalışıyorum orijinal kaşıntı bir cevap olarak gönderdi . Daha iyi çözümleriniz varsa bunu kesmek için çekinmeyin.


İlgili: Unix SE
kenorb'da

Sıklıkla gözden kaçan ve az kullanılan bir yardımcı program da locate, güncellenmiş dahili b'nin güncel olmayabilir. Ama hızlı.
michael

Bu soruyu konu dışı olarak kapatmak için oy kullanıyorum çünkü Unix & Linux
Dan Dascalescu

Yanıtlar:


481

-o"Veya" anlamına gelen kullanımı :

find Documents \( -name "*.py" -o -name "*.html" \)

Bu komut satırını programlı olarak oluşturmanız gerekir, ki bu o kadar kolay değildir.

Bash (veya Windows'ta Cygwin) kullanıyor musunuz? Eğer öyleyse, bunu yapabilmelisiniz:

ls **/*.py **/*.html

bu da programsal olarak daha kolay oluşturulabilir.


3
Genel bir kural olarak tüm bashisms'i ve daha fazlasını destekleyen zsh kullanıyorum.
Xiong Chiamiov

12
Zsh **yinelemeli arama için destekler ; Bash yalnızca 4.0 ve sonraki sürümlerde ve yalnızca shopt -s globstar.
ephemient

2
Kaç tane argüman olabilir? Oluşturmak için potansiyel olarak büyük bir .gcda (kapsama verileri) dosyaları listem var
Jasper Blues

40
Kullanıyorsanız, iki -names'yi köşeli parantez içine almanız gerekir -exec. Ör.find Documents \( -name "*.py" -o -name "*.html" \) -exec file {} \;
artbristol

2
@artbristol yorumu, örneğin -print0boşluklu dosya adlarını işlemek için bir ekliyorsanız çok önemlidir .
nimrodm

63

Bulguların bazı sürümleri, çoğunlukla linux sistemlerinde, muhtemelen diğerlerinde, regex ile eşleşen adlara sahip dosyaları bulan -regex ve -regextype seçeneklerini de destekler.

Örneğin

find . -regextype posix-egrep -regex ".*\.(py|html)$" 

yukarıdaki örnekte hile yapmalı. Ancak bu, standart bir POSIX bulma işlevi değildir ve uygulamaya bağlıdır.


1
intersting ama diğer cevaplardan daha karmaşık
m1k3y3

12
Daha basit: find . -regex ".*\.\(py\|html\)$"bu, Emacs tarzı normal ifadelerin varsayılanlarını biraz farklı olduğu için işe yarar, bu nedenle normal ifade türünü belirtmeniz gerekmez.
robru

2
Çok fazla ifadeniz varsa -regextype posix-egrepkullanışlıdır (aksi takdirde çok sayıda karakterden kaçmanız gerekir). Bu bir Windows dağıtım zip oluşturmak için bir dist-hook için kullandığım find komutudur (değiştirmek için dosyaları bulur ve dosya içi dos-eol olarak değiştirir): find -regextype posix-egrep -regex ".*(\.([chyl]|def|cpy|cob|conf|cfg)|(README|ChangeLog|AUTHORS|ABOUT-NLS|NEWS|THANKS|TODO|COPYING.*))$" -exec sed -i -e 's/\r*$/\r/' {} \;
Simon Sobisch

32

Programlı olarak aşağıdakilerle -nameayırarak daha fazla cümle ekleyebilirsiniz -or:

find Documents \( -name "*.py" -or -name "*.html" \)

Veya bunun yerine basit bir döngüye gidin:

for F in Documents/*.{py,html}; do ...something with each '$F'... ; done

@ user2284570: o zaman ya *.pydosya yoktur ya da bazı garip sürümleriniz vardır find. Yukarıda listelenen komut gayet iyi çalışıyor.
Stephan202

Hayır, kullanıyorum -iname. *.pyDosyaları yalnızca son konuma yazarsa döndürür ( iname *.htmlilk ifade de öyle) . Debian'daki komutu kullanıyorum.
user2284570

Alıntı kullanıyor musunuz? Bu çok önemli.
Stephan202

1
-Ya da mı yoksa -o mu?
Stephane

1
@StephaneEybert: ya iyi, ama sadece ikincisi POSIX uyumlu (man sayfasına göre).
Stephan202

16

Bu, linux üzerindeki tüm .c veya .cpp dosyalarını bulur

$ find . -name "*.c" -o -name "*.cpp"

Bazı ek modlar yapmadığınız sürece çıkış karakterli parantezlere ihtiyacınız yoktur. Burada man sayfasından desen eşleşirse yazdırın diyorlar. Belki de baskıyı kontrol etmeye çalışıyorlar. Bu durumda -print bir koşullu olarak hareket eder ve bir "VE" koşullu olur. .C dosyalarının yazdırılmasını engeller.

$ find .  -name "*.c" -o -name "*.cpp"  -print

Ancak orijinal cevabı beğenirseniz, baskıyı kontrol edebilirsiniz. Bu, tüm .c dosyalarını da bulacaktır.

$ find . \( -name "*.c" -o -name "*.cpp" \) -print

Tüm c / c ++ kaynak dosyaları için son bir örnek

$ find . \( -name "*.c" -o -name "*.cpp"  -o -name "*.h" -o -name "*.hpp" \) -print

11

Benzer bir ihtiyacım vardı. Bu benim için çalıştı:

find ../../ \( -iname 'tmp' -o -iname 'vendor' \) -prune -o \( -iname '*.*rb' -o -iname '*.rjs' \) -print

3
Mükemmel. Ama onsuz çalışmıyor biraz garip buluyorum()
pedrofurla

Eşleşen dosyaları bulmak istedim. * .C * .cpp veya * .cc Yalnızca iki adlı kalıplarla, ailelere ihtiyacım yoktu, ancak iki adlı kalıplarla birleştirilen üç adlı kalıplarla find -name "*.cpp" -o -name "*.c" -o -name "*.cc" -print0, ikinci veya operatörü gruplandırın. find -name "*.cpp" -o \( -name "*.c" -o -name "*.cc" \) -print0Her zaman "doğru" olan -print0 mantığı etkilemiş olabilir.
cardiff space man

5

Benim varsayılan değerim:

find -type f | egrep -i "*.java|*.css|*.cs|*.sql"

findBrendan Long ve Stephan202 ve ark.'nın daha az süreç yoğun uygulaması gibi:

find Documents \( -name "*.py" -or -name "*.html" \)


3
bu normal egrepifadenin doğru kullanımı değildir , bunun yerine normal ifadenin kullanılması gereken bir kabuk küresi vardır. (Ayrıca, tipik findkullanım şöyledir: find {directory} [options...] [action]burada, impl'ye bağlı olarak, directoryvarsayılan olabilir .ve actionvarsayılan olarak kullanılabilir -print, ancak açık olacağım.) Bunun yerine, şöyle bir şey kullanın: find . -type f -print | egrep -i '\.java$|\.css$|\.cs$|\.sql$' Ama aynı zamanda, gerçekten hızlı bir alternatif olarak find, biri de locatebenzer bir şekilde deneyin (bir dosya listesi için dahili bir
michael

2
#! /bin/bash
filetypes="*.py *.xml"
for type in $filetypes
do
find Documents -name "$type"
done

basit ama çalışıyor :)


1

Bazı dosyalar dışında alt dizinlerdeki tüm dosyaları kaldırmam gerekiyordu. Aşağıdakiler benim için çalıştı (üç desen belirtildi):

find . -depth -type f -not -name *.itp -and -not -name *ane.gro -and -not -name *.top -exec rm '{}' +

1

Desenli parantezler \(\)ile isim deseni için gereklidiror

find Documents -type f \( -name "*.py" -or -name "*.html" \)

andOperatör ile isim kalıbı için gerekli olmasa da

find Documents -type f ! -name "*.py" -and ! -name "*.html" 

0

Bu AIX korn kabuğu üzerinde çalışır.

find *.cbl *.dms -prune -type f -mtime -1

Bu, yalnızca şu anki dizinde alt dizinleri atlayarak 1 günlük aramaya sahip olan *.cblveya *.dmsbu sürümleri içerir.


0
find MyDir -iname "*.[j][p][g]"
+
find MyDir -iname "*.[b][m][p]"
=
find MyDir -iname "*.[jb][pm][gp]"

2
İkincisinin foo.jmg ile eşleşmeyeceğini, ancak ilk ikisinin hiçbirinin eşleşmeyeceğini unutmayın.
bakır.

0

Ne dersin

ls {*.py,*.html}

Dosya adlarında .py veya .html ile biten tüm dosyaları listeler

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.