grep rekursif: kecualikan direktori tertentu

49

Saya menggunakan grep rekursif banyak untuk menemukan file sumber dengan konten tertentu.

grep -Rni "myfunc" .

Pada basis kode yang besar, ini bisa lambat, jadi saya menggunakan --incldue untuk membatasi ekstensi / daftar putih.

grep -Rni --include=*.java "myfunc" .

Namun, akan lebih efisien untuk mengecualikan (memangkas) seluruh subdirektori, saya pikir:

grep -Rni --exclude=/.svn/ "myfunc" .

Tetapi --exclude hanya mendukung pola file seperti * .java di atas. Bagaimana saya bisa mengecualikan direktori?

gabor
sumber

Jawaban:

10

Anda mungkin melihat ack .

Saya baru saja mulai menggunakannya tetapi tampaknya cocok untuk ini.

Alex Feinman
sumber
ack terlihat cukup bagus. bagus karena secara intuitif mengecualikan file yang tidak diinginkan. opsi --nogroup memberikan output yang mirip dengan grep -Rni
gabor
2
Ack agak lambat. Anda dapat mencoba The Silver Searcher (Ag) atau ripgrep (rg).
user31389
62
grep -r --exclude-dir=dev --exclude-dir=sys --exclude-dir=proc PATTERN data

Sumber: https://stackoverflow.com/questions/2799246/grep-excluding-a-specific-folder-using

Henrik
sumber
17
Perhatikan bahwa ini secara rekursif tidak termasuk. ./devakan dikecualikan SEPANJANG DENGAN ./foo/bar/dev. Gunakan --exclude-dir=./devhanya berlaku untuk kasus pertama.
Cory Walker
4
Anda juga dapat mempersingkat ini dengan globbing: bash grep -r --exclude-dir={dev,sys,proc} PATTERN data Satu-satunya masalah dengan globbing adalah saya tidak bisa membuatnya bekerja di bash saya. Dalam hal ini saya harus memisahkan mereka.
B01
3
Juga mencatat bahwa {} hanya berfungsi jika Anda memasukkan lebih dari 1 entri, itu berarti --exclude-dir = {home, .svn} berfungsi tetapi --exclude-dir = {. Svn} tidak akan berfungsi. Membuang-buang waktu saya untuk mencari tahu mengapa {} tidak berhasil karena saya menguji dengan 1 entri di tempat pertama.
林果 皞
Jika Anda menggunakan {}satu entri, Anda mungkin perlu koma unary untuk menjadikannya array (tidak yakin bagaimana Bash mengatasinya). Alih-alih melakukan itu, saya malah membuat alias di .bash_aliases saya yang melingkupi daftar folder yang biasanya ingin saya kecualikan, misalnya .git, .svn, .hg, .cache, dan kemudian saya tambahkan melalui loop dengan --exclude-dir $dirdan kemudian rentangkan array itu ke alias grep.
dragon788
6

Anda dapat menggunakan find sebagai gantinya:

find . -not -path "*/.svn*" -not -type d -exec grep -ni "myfunc" {} \; -print

OK, jadi itu sedikit mundur, Anda mendapatkan hasil grep pertama dan kemudian jalan. Mungkin orang lain punya jawaban yang lebih baik?

Josh
sumber
3
ok, saya sangat menyukainya. tentu saja menemukan jauh lebih fleksibel. satu-satunya perbedaan antara output adalah bahwa "grep -Rni" akan mencetak nama file untuk setiap pertandingan, sedangkan "find -exec grep" akan mencetak nama file pada satu baris dan kemudian satu baris untuk setiap pertandingan (dengan nomor baris dan konten baris ). menggunakan "grep -Hni" pasukan nama file yang akan ditampilkan pada setiap baris
gabor
Terima kasih telah memberikan satu-satunya jawaban yang bekerja untuk sistem yang berkerak ini, tanpa grep --exclude-dir, tetapi masih harus dikerjakan
Dmitri DB
2

Berikut ini adalah contoh lengkap dari skrip di salah satu proyek saya yang mungkin bisa membantu, saya menyebut file ini "all_source" (ditandai sebagai executable) dan memasukkannya ke dalam direktori root proyek saya kemudian memanggilnya seperti grep myfunc $(./all_source)jenis di akhir skrip yang benar-benar pilihan.

#!/bin/bash

find . \
    -type d \( \
            -wholename './lib' -o \
            -wholename './vc6' -o \
            -name 'gen' -o \
            -name '.svn' \
            \) -prune -o \
    -type f \( \
            -name '*.h' -o \
            -name '*.cpp' -o \
            -name '*.c' -o \
            -name '*.lua' -o \
            -name '*.*awk' \) -print \
    | sort

Script ini mengembalikan semua nama file dalam proyek yang cocok *.h, *.cpp, *.c, *.lua, *.*awk, tetapi tidak mencari di semua folder bernama .svn dan folder gen serta melewatkan folder untuk ./libdan ./vc6(tetapi hanya yang langsung dari root proyek). Jadi, ketika Anda melakukannya grep myfunc $(./all_source)hanya greps dalam file-file itu. Anda harus memanggil ini dari root dir proyek juga.

Mike Nelson
sumber
0

Ada juga opsi -proune untuk menemukan:

 find . -path "*/.svn*" -prune -o -not -type d -exec grep -ni "myfunc" {} \; -print
misiu_mp
sumber
0

Anda dapat mencoba melakukan ini:

grep -R  "myfunc" . | grep -v path_to_exclude/

Misalnya: Jika Anda tidak ingin mencari konten dalam file log lakukan saja hal berikut:

grep -R "myfunc" . | grep -v log/
Akshatha
sumber