bagaimana cara menggunakan opsi grep --include untuk beberapa jenis file?

98

Ketika saya ingin grep semua file html di beberapa direktori, saya melakukan hal berikut

grep --include="*.html" pattern -R /some/path

yang bekerja dengan baik. Masalahnya adalah bagaimana cara grep semua file html, htm, php di beberapa direktori?

Dari Gunakan grep --exclude / - include syntax agar tidak grep melalui file tertentu , sepertinya saya bisa melakukan hal berikut

grep --include="*.{html,php,htm}" pattern -R /some/path

Tapi sayangnya, itu tidak akan berhasil untuk saya.
FYI, versi grep saya adalah 2.5.1.

tianyapiaozi
sumber

Jawaban:

137

Anda dapat menggunakan banyak --includebendera. Ini bekerja untuk saya:

grep -r --include=*.html --include=*.php --include=*.htm "pattern" /some/path/

Namun, Anda dapat melakukan seperti yang Deruijterdisarankan. Ini bekerja untuk saya:

grep -r --include=*.{html,php,htm} "pattern" /some/path/

Jangan lupa bahwa Anda dapat menggunakan finddan xargsuntuk hal semacam ini untuk:

find /some/path/ -name "*.htm*" -or -name "*.php" | xargs grep "pattern"

HTH

Steve
sumber
1
Saya melihat masalahnya. Saya menggunakan --include = " . {Html, php}" untuk mencegah shell meluas ' ' yang pada saat yang sama menghentikan shell untuk memperluas {html, php}. Tampaknya tanda yang sama di --include = * dapat mencegah shell memperluas '*'.
tianyapiaozi
xargs sebenarnya bukan pengganti; sering kali ketika Anda membutuhkan fitur ini, Anda berurusan dengan lebih banyak file daripada yang akan ditangani xargs.
James Moore
2
@JamesMoore: Lihat GNU Parallel . Ini sering dapat digunakan sebagai pengganti xargs. Ini juga layak untuk dibaca dengan cepat. HTH.
Steve
3
@tianyapiaozi: Anda benar bahwa kutipan seputar perluasan brace adalah masalahnya; tanpa kutipan, bagaimanapun, *masih tunduk pada globbing sebagai bagian dari token yang disematkannya , kebetulan tidak cocok dengan apa pun dalam kasus ini, karena hanya file yang secara harfiah bernama sesuatu yang --include=foo.htmlcocok. Untuk amannya, kutip *(yang dapat Anda lakukan secara individu \*). Sebagai bonus tambahan, ini membuatnya lebih jelas secara visual bahwa bukan shell yang harus melakukan globbing dalam kasus ini.
mklement0
2
Adapun findsolusinya: menggunakan -exec grep "pattern" {} +daripada | xargs grep "pattern"lebih kuat (menangani nama file dengan spasi, misalnya) serta lebih efisien.
mklement0
32

Menggunakan {html,php,htm}hanya bisa bekerja sebagai ekspansi penjepit , yang merupakan tidak standar fitur (tidak POSIX-compliant) dari bash, ksh, dan zsh.

  • Dengan kata lain: jangan mencoba menggunakannya dalam skrip yang menargetkan /bin/sh- gunakan beberapa argumen eksplisit--include dalam kasus itu.

  • grepsendiri tidak mengerti {...}notasi.

Agar perluasan tanda kurung kurawal dapat dikenali, itu harus berupa tanda kutip (bagian dari a) pada baris perintah.

Ekspansi brace meluas ke beberapa argumen , jadi dalam kasus yang dihadapi grepakhirnya melihat beberapa --include=... opsi, seperti jika Anda meneruskannya satu per satu.

Hasil ekspansi brace tunduk pada globbing (perluasan nama file) , yang memiliki kendala :

  • Setiap argumen yang dihasilkan selanjutnya dapat diperluas ke nama file yang cocok jika kebetulan berisi karakter meta globbing tanpa tanda kutip seperti *.
    Meskipun hal ini tidak mungkin terjadi dengan token seperti --include=*.html(mis., Anda harus memiliki file yang secara harfiah dinamai sesuatu yang --include=foo.htmlcocok), perlu diingat secara umum.

  • Jika nullglobopsi shell kebetulan dihidupkan ( shopt -s nullglob) dan globbing tidak cocok dengan apa pun , argumen akan dibuang .

Oleh karena itu, untuk solusi yang sepenuhnya kuat , gunakan yang berikut ini:

grep -R '--include=*.'{html,php,htm} pattern /some/path
  • '--include=*.'diperlakukan sebagai literal , karena dikutip tunggal ; ini mencegah interpretasi yang tidak disengaja *sebagai karakter yang menggelembung.

  • {html,php,htm}, the - of needs - unquoted brace expansion [1] , meluas menjadi 3 argumen, yang, karena {...} mengikuti '...'token secara langsung , termasuk token tersebut.

  • Oleh karena itu, setelah penghapusan kutipan oleh shell, berikut 3 literal argumen akhirnya dilewatkan kegrep :

    • --include=*.html
    • --include=*.php
    • --include=*.htm

[1] Lebih tepatnya, hanya bagian yang relevan dengan sintaks dari perluasan tanda kutip yang harus tidak diberi tanda kutip , elemen daftar mungkin masih dikutip secara individual dan harus berisi karakter meta penggabungan yang dapat mengakibatkan penggumpalan yang tidak diinginkan setelah perluasan tanda kurung; sementara tidak diperlukan dalam kasus ini, di atas dapat ditulis sebagai
'--include=*.'{'html','php','htm'}

mklement0
sumber
1
Terima kasih banyak untuk posting ini Pos yang bagus tidak hanya menjawab pertanyaan tetapi juga mengajari Anda sesuatu yang baru! Ini sangat berguna bagi kita yang menulis tentang sesuatu yang harus sesuai dengan POSIX. Siapapun yang menggunakan Mac OS X harus melihat di sini!
sabalaba
@sabalaba: Saya senang mendengarnya, tetapi untuk memperjelas: meskipun ekspansi brace tidak sesuai dengan POSIX, ia bekerja dengan bashplatform apa pun yang bashberjalan.
mklement0
9

Coba hapus tanda kutip ganda

grep --include=*.{html,php,htm} pattern -R /some/path
Deruijter
sumber
@tianyapiaozi Coba grep --include=\*.{html,php,htm} pattern -R /some/path. Itu berhasil untuk saya.
Hyunjun Kim
4

apakah ini tidak bekerja?

  grep pattern  /some/path/*.{html,php,htm} 
Vijay
sumber
Tidak juga. File mungkin berada di subdirektori subdirektori
tianyapiaozi
2

Coba ini. -r akan melakukan pencarian rekursif. -s akan menyembunyikan kesalahan file tidak ditemukan. -n akan menunjukkan nomor baris file tempat pola ditemukan.

    grep "pattern" <path> -r -s -n --include=*.{c,cpp,C,h}
Pradeep
sumber
Ini adalah jawaban terbaik untuk saya khususnya, dan saya pikir Anda bisa meletakkan -rsn daripada -r -s -n (tapi itu nitpicking).
ramping
Biasanya saya menggunakan -rns . Untuk kejelasan dalam contoh, saya harus menyebutkan -r -n -s :-) Senang bisa membantu.
Pradeep
Saya merekomendasikan menambahkan -Ike set standar. Ini melewatkan file biner (yang hampir tidak pernah dicari) sehingga meningkatkan efisiensi. Lalu kita pergi grep -rIns ...yang memainkan akustik dengan baik :)
berdarah
2

Ia bekerja untuk tujuan yang sama, tetapi tanpa --includepilihan. Ia bekerja pada grep 2.5.1 juga.

grep -v -E ".*\.(html|htm|php)"
Kohei Mikami
sumber
0

Gunakan grepdengan findperintah

find /some/path -name '*.html' -o -name '*.htm' -o -name '*.php' -type f 
 -exec grep PATTERN {} \+

Anda dapat menggunakan -regexdan -regextypeopsi juga.

Pangeran John Wesley
sumber