Bagaimana saya bisa mengecualikan direktori dari grep -R?

670

Saya ingin melintasi semua subdirektori, kecuali direktori "node_modules".

TIMEX
sumber
14
Cukup ketik "man grep" dan Anda akan melihat opsi --exclude, dan --exclude-dir terdaftar di sana - dari judul pertanyaan ini, saya berasumsi Anda sudah tahu tentang grep ...
arcseldon
35
Jika Anda mengambil kode dalam repositori git dan node_modulesberada di Anda .gitignore, git grep "STUFF"adalah cara termudah. git grepmencari file yang dilacak di pohon yang berfungsi, mengabaikan semuanya dari.gitignore
0xcaff
2
Contoh untuk simpul: grep -R --exclude-dir={node_modules,bower_components} "MyString" | cut -c1-"$COLUMNS"- selanjutnya Anda selalu bisa alias ini di shell untuk 'nodegrep' atau apa pun dan menggunakan argumen perintah sebagai input string ..
bshea

Jawaban:

395

SOLUSI 1 (gabungkan finddan grep)

Tujuan dari solusi ini bukan untuk menangani grepkinerja tetapi untuk menunjukkan solusi portabel: juga harus bekerja dengan busybox atau versi GNU yang lebih tua dari 2,5.

Gunakan find, untuk mengecualikan direktori foo and bar:

find /dir \( -name foo -prune \) -o \( -name bar -prune \) -o -name "*.sh" -print

Kemudian gabungkan finddan penggunaan non-rekursif grep, sebagai solusi portabel:

find /dir \( -name node_modules -prune \) -o -name "*.sh" -exec grep --color -Hn "your text to find" {} 2>/dev/null \;

SOLUSI 2 (penggunaan rekursif grep):

Anda sudah tahu solusi ini, tetapi saya menambahkannya karena ini solusi terbaru dan efisien. Perhatikan ini adalah solusi yang kurang portabel tetapi lebih dapat dibaca manusia.

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

Untuk mengecualikan beberapa direktori, gunakan --exclude-dirsebagai:

--exclude-dir={node_modules,dir1,dir2,dir3}

SOLUSI 3 (Ag)

Jika Anda sering mencari melalui kode, Ag (The Silver Searcher) adalah alternatif yang jauh lebih cepat daripada grep, yang disesuaikan untuk mencari kode. Misalnya, secara otomatis mengabaikan file dan direktori yang terdaftar .gitignore, sehingga Anda tidak harus terus melewati opsi pengecualian yang rumit untuk grepatau find.

hornetbzz
sumber
2
kombinasi ini mencari lebih cepat daripada --exclude-dir=dirdan itu menunjukkan hasil dengan warna - mudah dibaca
Maxim Yefremov
27
"kombinasi ini" find ... -exectidak lebih cepat dari grep --exclude-dirpada saya. Keuntungan besar untuk grep (sekitar lima kali lebih cepat dengan file 26k +, disaring dari 38k + pada HDD), kecuali Anda mengganti \;dengan +untuk combo find / exec. Maka grep "hanya" sekitar 30% lebih cepat. Sintaks grep juga dapat dibaca manusia :).
Kjell Andreassen
Setuju, karena ini jelas. Beberapa busyboxes tidak memiliki perintah GREP.
hornetbzz
10
juga mencatat bahwa Anda dapat mengecualikan beberapa dengan--exclude-dir={dir1,dir2}
suh
4
Saya tidak sedikit terkejut bahwa itu node_modulesadalah contoh kanonik.
pdoherty926
984

Versi terbaru GNU Grep (> = 2.5.2 ) menyediakan:

--exclude-dir=dir

yang mengecualikan direktori yang cocok dengan pola dirdari pencarian direktori rekursif.

Jadi kamu bisa melakukan:

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

Untuk informasi lebih lanjut tentang sintaks dan penggunaan, lihat

Untuk GNU Greps dan POSIX Grep yang lebih lama , gunakan findseperti yang disarankan dalam jawaban lain.

Atau cukup gunakan ack( Edit : atau The Silver Searcher ) dan selesai saja!

Johnsyweb
sumber
4
@Manocho: Jika menurut Anda ackhebat, coba The Silver Searcher dan lihat kecepatannya meningkat!
Johnsyweb
30
Sintaks untuk yang tidak sabar: --exclude-dir=dirmenggunakan greppola ekspresi reguler, bukan globbing file shell. Pola bekerja di jalur relatif ke direktori Anda saat ini. Jadi gunakan pola --exclude-dir=dir, bukan --exclude-dir="/root/dir/*".
tanius
15
Jika Anda ingin mengecualikan beberapa dir dari pencarian, apakah ada opsi yang lebih baik daripada menggunakan $ grep -r --exclude-dir=dir1 --exclude-dir=dir2 "string" /path/to/search/dir:?
Darshan Chaudhary
4
Saya mungkin menghabiskan terlalu banyak waktu untuk hal ini daripada orang waras, tapi saya tidak bisa seumur hidup mencari tahu bagaimana mengecualikan subdirektori dari pencarian - grep -r --exclude-dir=public keyword .bekerja, tetapi grep -r --exclude-dir='public/dist' keyword .tidak. Saya mencoba menambahkan regex wildcard, melarikan diri karakter dll, tetapi sepertinya tidak ada yang membantu.
dkobozev
73
Kecualikan beberapa direktori seperti:grep -r "Request" . --exclude-dir={node_modules,git,build}
maverick97
78

Jika Anda ingin mengecualikan beberapa direktori :

"r" untuk rekursif, "l" untuk mencetak hanya nama file yang mengandung kecocokan dan "i" untuk mengabaikan perbedaan huruf besar-kecil:

grep -rli --exclude-dir={dir1,dir2,dir3} keyword /path/to/search

Contoh: Saya ingin mencari file yang mengandung kata 'halo'. Saya ingin mencari di semua direktori linux saya kecuali direktori proc , direktori boot , direktori sys dan direktori root :

grep -rli --exclude-dir={proc,boot,root,sys} hello /

Catatan: Contoh di atas harus root

Catatan 2 (menurut @skplunkerin): jangan tambahkan spasi setelah koma masuk {dir1,dir2,dir3}

Azodium
sumber
5
CATATAN: jangan tambahkan spasi setelah koma di{dir1,dir2,dir3}
skplunkerin
Terima kasih, berguna saat menerima melalui ruang kerja SVN:grep -Irsn --exclude-dir=.svn 'foo' .
RAM237
1
Anda bisa memberikan --exclude-diropsi beberapa kali.
Walf
45

Sintaks ini

--exclude-dir={dir1,dir2}

diperluas oleh shell (misalnya Bash), bukan oleh grep, ke dalam ini:

--exclude-dir=dir1 --exclude-dir=dir2

Mengutip akan mencegah shell mengembangkannya, jadi ini tidak akan berfungsi:

--exclude-dir='{dir1,dir2}'    <-- this won't work

Pola yang digunakan dengan pola --exclude-diryang sama dijelaskan dalam halaman manual untuk --excludeopsi:

--exclude=GLOB
    Skip files whose base name matches GLOB (using wildcard matching).
    A file-name glob can use *, ?, and [...]  as wildcards, and \ to
    quote a wildcard or backslash character literally.

Shell umumnya akan mencoba mengembangkan pola seperti itu sendiri, jadi untuk menghindari ini, Anda harus mengutipnya:

--exclude-dir='dir?'

Anda dapat menggunakan kurung kurawal dan mengutip dengan mengecualikan pola bersama seperti ini:

--exclude-dir={'dir?','dir??'}

Pola dapat menjangkau beberapa segmen jalur:

--exclude-dir='some*/?lse'

Ini akan mengecualikan direktori seperti topdir/something/else.

Derek Veit
sumber
14

Sering menggunakan ini:

grepdapat digunakan bersamaan dengan -r(rekursif), i(abaikan case) dan -o(hanya mencetak bagian yang cocok dari garis). Untuk mengecualikan filespenggunaan --excludedan untuk mengecualikan direktori gunakan --exclude-dir.

Menyatukannya Anda berakhir dengan sesuatu seperti:

grep -rio --exclude={filenames comma separated} \
--exclude-dir={directory names comma separated} <search term> <location>

Menggambarkannya membuatnya terdengar jauh lebih rumit daripada yang sebenarnya. Lebih mudah diilustrasikan dengan contoh sederhana.

Contoh:

Misalkan saya sedang mencari proyek saat ini untuk semua tempat di mana saya secara eksplisit menetapkan nilai string debuggerselama sesi debugging, dan sekarang ingin meninjau / menghapus.

Saya menulis sebuah skrip yang dipanggil findDebugger.shdan digunakan grepuntuk menemukan semua kejadian. Namun:

Untuk pengecualian file - Saya ingin memastikan bahwa .eslintrcdiabaikan (ini sebenarnya memiliki aturan linting debuggersehingga harus dikecualikan). Demikian juga, saya tidak ingin skrip saya sendiri dirujuk dalam hasil apa pun.

Untuk pengecualian direktori - Saya ingin mengecualikan node_moduleskarena berisi banyak perpustakaan yang melakukan referensi debuggerdan saya tidak tertarik dengan hasil tersebut. Juga saya hanya ingin menghilangkan .ideadan .gitmenyembunyikan direktori karena saya juga tidak peduli dengan lokasi pencarian tersebut, dan ingin tetap menjadi pemain pencarian.

Jadi di sini adalah hasilnya - saya membuat skrip bernama findDebugger.shdengan:

#!/usr/bin/env bash
grep -rio --exclude={.eslintrc,findDebugger.sh} \
--exclude-dir={node_modules,.idea,.git} debugger .
arcseldon
sumber
Saya percaya opsi "r" harus dicetak dengan huruf besar "-R".
hornetbzz
1
Menarik. "r" selalu bekerja untuk saya di nix dan mac.
arcseldon
Ketika saya menulis jawaban saya , saya menggunakan -R(saya tidak ingat mengapa sekarang). Saya biasanya menggunakan -r. Ternyata versi huruf besar mengikuti symlinks . TIL.
Johnsyweb
@ Johnsyweb - terima kasih. memutakhirkan jawaban Anda - jangan ingat kapan, kemungkinan pada tahun 2016 ketika saya menambahkan jawaban ini :)
arcseldon
10

Anda dapat mencoba sesuatu seperti grep -R search . | grep -v '^node_modules/.*'

DipSwitch
sumber
34
Dalam beberapa kasus bukan solusi yang bagus. Sebagai contoh: Jika direktori 'node_modules' adalah direktori besar dengan banyak kecocokan positif palsu (maka kebutuhan untuk menyaring direktori) maka grep pertama menghabiskan banyak waktu mencari melalui sub-direktori dan KEMUDIAN grep filtering kedua keluar pertandingan. Lebih cepat untuk mengecualikan node_modules di grep pertama itu sendiri.
GuruM
2
saya tidak peduli tentang kelambatan, saya bisa melihat perintah dan tahu apa fungsinya
Funkodebat
1
Ditto untuk komentar Guru. Grep /varhang ketika hits /var/rundalam kasus saya. Karenanya alasan saya ingin menghindari direktori di tempat pertama.
jww
3
--exclude-diradalah solusi terbaik pada 2016.
Omar Tariq
10

Jika Anda mengambil kode di repositori git dan node_modulesberada di Anda .gitignore, Anda dapat menggunakannya git grep. git grepmencari file yang dilacak di pohon yang berfungsi, mengabaikan semuanya.gitignore

git grep "STUFF"
0xcaff
sumber
Ini tip yang sangat berguna. Terima kasih.
NKM
4

Sangat berguna, terutama bagi mereka yang berurusan dengan Node.js di mana kami ingin menghindari mencari di dalam "node_modules":

find ./ -not -path "*/node_modules/*" -name "*.js" | xargs grep keyword
Nestor Urquiza
sumber
2

Perintah kerja sederhana:

root/dspace# grep -r --exclude-dir={log,assetstore} "creativecommons.org"

Di atas saya menerima teks "creativecommons.org" di direktori saat ini "dspace" dan mengecualikan dirs {log, assetstore}.

Selesai

Kotoran
sumber
Rapi, termasuk beberapa direktori dalam kurung
Mijo
2

Banyak jawaban yang benar telah diberikan di sini, tetapi saya menambahkan yang ini untuk menekankan satu poin yang menyebabkan beberapa upaya tergesa-gesa untuk gagal sebelumnya: exclude-dirmengambil pola , bukan jalur ke direktori.

Katakanlah pencarian Anda adalah:

grep -r myobject

Dan Anda perhatikan bahwa output Anda berantakan dengan hasil dari src/other/objects-folder. Perintah ini tidak akan memberi Anda hasil yang diinginkan:

grep -r myobject --exclude-dir=src/other/objects-folder

Dan Anda mungkin bertanya-tanya mengapa exclude-dirtidak bekerja! Untuk benar-benar mengecualikan hasil dari objects-folder, cukup lakukan ini:

grep -r myobject --exclude-dir=objects-folder

Dengan kata lain, cukup gunakan nama folder , bukan path. Jelas sekali Anda mengetahuinya.

Dari halaman manual:

--exclude-dir = GLOB
Lewati direktori baris perintah dengan akhiran nama yang cocok dengan pola GLOB. Saat mencari secara rekursif, lewati setiap subdirektori yang nama dasarnya cocok dengan GLOB. Abaikan pemotongan garis miring yang berlebihan di GLOB.

Nagev
sumber
2

Yang ini bekerja untuk saya:

grep <stuff> -R --exclude-dir=<your_dir>
angelo.mastro
sumber
5
Bagaimana jawaban ini berbeda dari apa yang sudah diposting?
aexl
1
find . ! -name "node_modules" -type d 
Mendongkrak
sumber
-1

Cara yang lebih sederhana adalah dengan memfilter hasil Anda menggunakan "grep -v".

grep -i needle -R * | grep -v node_modules

Morris
sumber
12
Ini jawaban yang sama efektifnya dengan DipSwitch yang diberikan 3 tahun sebelumnya. Ini memiliki masalah yang sama juga.
jww