pola `find -name` yang cocok dengan banyak pola

335

Saya mencoba untuk mendapatkan daftar semua file python dan html dalam direktori dengan perintah find Documents -name "*.{py,html}".

Lalu datanglah halaman manual:

Kawat gigi di dalam pola ('{}') tidak dianggap istimewa (yaitu, temukan. -Nama 'foo {1,2}' cocok dengan file bernama foo {1,2}, bukan file foo1 dan foo2.

Karena ini adalah bagian dari rantai-pipa, saya ingin dapat menentukan ekstensi mana yang cocok saat runtime (tidak ada hardcoding). Jika menemukan tidak bisa melakukannya, perl one-liner (atau serupa) akan baik-baik saja.

Sunting: Jawaban yang akhirnya saya dapatkan mencakup semua jenis omong kosong, dan agak panjang juga, jadi saya mempostingnya sebagai jawaban untuk gatal asli yang saya coba gores. Jangan ragu untuk meretasnya jika Anda memiliki solusi yang lebih baik.

Xiong Chiamiov
sumber
Utilitas yang sering diabaikan dan kurang dimanfaatkan juga locate, meskipun dengan peringatan bahwa pembaruan internal mungkin tidak up-to-date. Tapi ini cepat.
michael
Saya memberikan suara untuk menutup pertanyaan ini sebagai di luar topik karena itu milik Unix & Linux
Dan Dascalescu

Jawaban:

481

Gunakan -o, yang berarti "atau":

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

Anda harus membangun baris perintah itu secara terprogram, yang tidak mudah.

Apakah Anda menggunakan bash (atau Cygwin di Windows)? Jika ya, Anda harus dapat melakukan ini:

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

yang mungkin lebih mudah dibangun secara programatik.

RichieHindle
sumber
3
Saya menggunakan zsh, yang, sebagai aturan umum, mendukung semua bashism, plus lebih banyak.
Xiong Chiamiov
12
Zsh mendukung **pencarian rekursif; Bash hanya mendukungnya dalam versi 4.0 dan lebih tinggi, dan hanya dengan shopt -s globstar.
ephemient
2
Berapa banyak arg yang bisa Anda miliki? Saya mempunyai banyak daftar file .gcda (data cakupan) yang berpotensi untuk dibangun
Jasper Blues
40
Anda harus mengelilingi kedua -nametanda kurung, jika Anda menggunakan -exec. Misalnyafind Documents \( -name "*.py" -o -name "*.html" \) -exec file {} \;
artbristol
2
Komentar @artbristol sangat relevan jika, misalnya, Anda menambahkan -print0untuk menangani nama file dengan spasi.
nimrodm
63

Beberapa edisi find, kebanyakan pada sistem linux, mungkin pada yang lain juga mendukung opsi -regex dan -regextype, yang menemukan file dengan nama yang cocok dengan regex.

sebagai contoh

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

harus melakukan trik dalam contoh di atas. Namun ini bukan fungsi menemukan POSIX standar dan tergantung implementasi.

intelekt
sumber
1
memotong tetapi lebih
rumit
12
Simpler: find . -regex ".*\.\(py\|html\)$"ini berfungsi karena menemukan default untuk ekspresi reguler gaya Emacs, yang sedikit berbeda, jadi Anda tidak perlu menentukan regextype.
robru
2
Jika Anda memiliki banyak ekspresi -regextype posix-egrepberguna (jika tidak, Anda harus keluar dari banyak karakter). Ini adalah perintah find yang saya gunakan untuk dist-hook membangun zip distribusi Windows (temukan file untuk diubah dan di-file mengubahnya menjadi dos-eol): 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

Anda dapat menambahkan beberapa -nameklausa secara terprogram , dipisahkan oleh -or:

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

Atau, gunakan loop sederhana sebagai gantinya:

for F in Documents/*.{py,html}; do ...something with each '$F'... ; done
Stephan202
sumber
@ user2284570: maka tidak ada *.pyfile atau Anda memiliki beberapa versi aneh find. Perintah yang tercantum di atas berfungsi dengan baik.
Stephan202
Tidak, saya menggunakan -iname. Ini mengembalikan *.pyfile hanya jika menulisnya di posisi terakhir (demikian iname *.htmljuga ekspresi pertama) . Saya menggunakan perintah pada Debian.
user2284570
Apakah Anda menggunakan kutipan? Itu sangat penting.
Stephan202
1
Apakah itu -atau -o?
Stephane
1
@StephaneEybert: keduanya baik-baik saja, tetapi hanya yang terakhir yang sesuai dengan POSIX (menurut halaman manual).
Stephan202
16

Ini akan menemukan semua file .c atau .cpp di linux

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

Anda tidak perlu tanda kurung yang lolos kecuali Anda melakukan beberapa mod tambahan. Di sini, dari halaman manual mereka mengatakan jika polanya cocok, cetaklah. Mungkin mereka mencoba mengendalikan pencetakan. Dalam hal ini -print bertindak sebagai kondisi dan menjadi kondisi "DAN". Ini akan mencegah file .c dari dicetak.

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

Tetapi jika Anda menyukai jawaban aslinya, Anda dapat mengontrol pencetakan. Ini akan menemukan semua file .c juga.

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

Satu contoh terakhir untuk semua file sumber c / c ++

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

Saya memiliki kebutuhan yang sama. Ini bekerja untuk saya:

find ../../ \( -iname 'tmp' -o -iname 'vendor' \) -prune -o \( -iname '*.*rb' -o -iname '*.rjs' \) -print
bkidd
sumber
3
Sempurna. Tetapi saya merasa agak aneh bahwa itu tidak bekerja tanpa()
pedrofurla
Saya ingin mencari file yang cocok dengan * .c * .cpp atau * .cc. Dengan hanya dua pola nama saya tidak perlu parens tetapi dengan tiga pola nama yang digabungkan dengan dua pola -o find -name "*.cpp" -o -name "*.c" -o -name "*.cc" -print0saya harus menggunakan sepasang parens untuk kelompok yang kedua atau operator. find -name "*.cpp" -o \( -name "*.c" -o -name "*.cc" \) -print0Mungkin -print0, yang selalu "benar" mempengaruhi logika.
Pria luar angkasa cardiff
5

Default saya adalah:

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

Seperti proses yang kurang intensif, findeksekusi oleh Brendan Long dan Stephan202 et al .:

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

PaSe
sumber
3
itu bukan penggunaan egrepregexp yang benar, melainkan, Anda memiliki shell glob di mana regexp harus digunakan. (Juga, findpenggunaan tipikal adalah find {directory} [options...] [action]:, di mana, tergantung pada impl, directorymungkin default ke ., dan actiondefault ke -print, tapi saya akan eksplisit.) Jadi, alih-alih, gunakan sesuatu seperti: find . -type f -print | egrep -i '\.java$|\.css$|\.cs$|\.sql$' Tapi juga, sebagai alternatif yang sangat cepat find, orang mungkin juga coba locatedengan cara yang sama (walaupun belum tentu up to date, karena ia meminta internal db untuk daftar file)
michael
2
#! /bin/bash
filetypes="*.py *.xml"
for type in $filetypes
do
find Documents -name "$type"
done

sederhana tapi berhasil :)

mnrl
sumber
1

Saya perlu menghapus semua file dalam direktori anak kecuali untuk beberapa file. Berikut ini berfungsi untuk saya (tiga pola ditentukan):

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

Kawat gigi dalam pola \(\)diperlukan untuk pola nama denganor

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

Sedangkan untuk pola nama dengan andoperator tidak diperlukan

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

Ini bekerja pada shell korn AIX.

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

Ini mencari *.cblatau *.dmsyang berumur 1 hari, dalam direktori saat ini saja, melewatkan sub-direktori.

Abdul M Gill
sumber
0
find MyDir -iname "*.[j][p][g]"
+
find MyDir -iname "*.[b][m][p]"
=
find MyDir -iname "*.[jb][pm][gp]"
pengguna7531934
sumber
2
Perhatikan bahwa yang terakhir akan cocok dengan foo.jmg tetapi tidak satu pun dari dua teratas akan.
tembaga. Bahwa
0

Bagaimana dengan

ls {*.py,*.html}

Ini mencantumkan semua file yang diakhiri dengan .py atau .html dalam nama file mereka

Dr_Hope
sumber