Pertanyaan Cara menggunakan perintah "grep" untuk menemukan teks termasuk subdirektori


Saya ingin mencari semua file yang berisi string teks tertentu. Itu grep perintah berfungsi, tetapi saya tidak tahu cara menggunakannya untuk setiap direktori (saya hanya bisa melakukannya untuk direktori saya saat ini). Saya mencoba membaca man grep, tetapi tidak menghasilkan bantuan apa pun.


292
2017-08-01 11:38


asal


grep -RIn <yor pattern> * Akan mencari dari direktori saat ini di semua file teks. Tidak yakin bagaimana melakukan pencarian saya secara rekursif dalam pola file seperti * .C dengan hanya grep
Wildcard dengan --include="*.C" pilihan, @ user311346, terima kasih kepada @Lekensteyn. - Bob Stein
Gunakan kombinasi find dan grep untuk mencari file secara rekursif untuk string di sub direktori saat ini dan semua. Periksa ini wilddiary.com/find-files-containing-my-text - Drona


Jawaban:


Akan lebih baik untuk digunakan

grep -rl "string" /path

dimana

  • -r (atau --recursive) opsi digunakan untuk melintasi juga semua sub-direktori /path, sedangkan
  • -l (atau --files-with-matches) opsi hanya digunakan untuk mencetak nama file yang cocok dengan file, dan bukan baris yang cocok (ini juga dapat meningkatkan kecepatan, mengingat itu grep berhenti membaca file pada pertandingan pertama dengan opsi ini).

375
2017-08-01 11:55



Sebenarnya jika "string" adalah pola teks untuk menemukan, lebih baik untuk menggunakan fungsi itu, jika tidak seseorang dapat menghadapi masalah ketika string mengandung dot atau karakter khusus yang memiliki makna dalam ekspresi reguler dan bukan hanya titik yang seharusnya ditemukan sebagai string , dengan adanya. Maka saya akan menggunakan -rlF switch, -F untuk "string tetap" (dan bukan regexp - misalnya). Tentu saja, jika tugas itu menggunakan regexps, maka permisi. Tentu, teori yang sama tanpa-r juga, saya sering melihat bahwa orang menganggap grep mencari "teks" dan itu dapat menyebabkan masalah yang khusus yang berarti sesuatu sebagai regexp. - LGB
Ada juga yang -i Bendera yang mengabaikan kasus. - Marco Ceppi♦
Saya hanya akan menunjukkan --recursive pilihan, ada banyak opsi dan skenario penggunaan yang bisa dibicarakan. Saya mulai dari jawaban diterima @dmityugov dan dimodifikasi untuk bekerja tanpa find. - enzotib
@ N.N .: selesai :-) - enzotib
@ScottBiggs: dengan opsi --include '*.h' - enzotib


Jika Anda mencari baris yang cocok dalam file, perintah favorit saya adalah:

grep -Hrn 'search term' path/to/files
  • -H menyebabkan nama file yang akan dicetak (tersirat ketika beberapa file dicari)
  • -r melakukan pencarian rekursif
  • -n menyebabkan nomor baris dicetak

path/to/files dapat . untuk mencari di direktori saat ini

Pilihan lebih lanjut yang menurut saya sangat berguna:

  • -I abaikan file biner (komplemen: -a perlakukan semua file sebagai teks)
  • -F memperlakukan search term sebagai literal, bukan ekspresi reguler
  • -i melakukan pencarian case-sensitive
  • --color=always untuk memaksa warna bahkan ketika piping melalui less. Untuk membuat less mendukung warna, Anda harus menggunakan -r pilihan:

    grep -Hrn search . | less -r
    
  • --exclude-dir=dir berguna untuk mengecualikan direktori seperti .svn dan .git.

Example output


136
2017-08-01 12:27



-H pada folder redundan, jika ada lebih dari satu file, seperti yang mungkin terjadi. Bahkan, kata halaman buku itu -H, --with-filename: Print the file name for each match. This is the default when there is more than one file to search. - enzotib
Saya tidak tahu itu, itu selalu bekerja seperti yang saya harapkan. Ini adalah perintah default saya ketika mencari file. - Lekensteyn
Apakah ada cara untuk hanya mempertimbangkan file dengan, katakanlah, .a extention (dan untuk menggabungkan ini dengan -r)? - user2413
@ user2413 Coba --include '*.*' - Lekensteyn
@enzotib Hanya FYI: Saya tidak mendapatkan output bersih yang bagus dari setiap baris di setiap file di mana teks saya muncul dengan -rln atau -rl, tapi saya lakukan dengan -Hrn. Redundan atau tidak, tampilannya seperti screenshot di atas dengan opsi -Hrn. Juga, tidak tampak seperti -n bekerja tanpa -H. - SgtPooki


Saya yakin Anda dapat menggunakan sesuatu seperti ini:

find /path -type f -exec grep -l "string" {} \;

Penjelasan dari komentar

find adalah perintah yang memungkinkan Anda menemukan file dan objek lain seperti direktori dan tautan dalam subdirektori dari jalur yang diberikan. Jika Anda tidak menentukan masker yang nama file harus dipenuhi, itu enumerasi semua objek direktori.

  • -type f menentukan bahwa ia harus memproses hanya file, bukan direktori, dll.
  • -exec grep menetapkan bahwa untuk setiap file yang ditemukan, harus menjalankan perintah grep, meneruskan nama file sebagai argumen untuk itu, dengan mengganti {} dengan nama file

21
2017-08-01 11:48



Hanya bagi mereka yang tidak tahu, menambahkan -name '*.py' membatasi kecocokan dengan file yang diakhiri dengan '.py'. - Daniel F
Saya suka bahwa ini mencakup klien yang tidak memiliki -R yang diimplementasikan dalam perintah grep mereka. - Aviose


Perintah default saya adalah

grep -Rin string *

Saya menggunakan huruf kapital 'R' karena ls menggunakannya untuk rekursif. Karena grep menerima keduanya, tidak ada alasan untuk tidak menggunakannya.

EDIT: per HVNSweeting, rupanya -R akan mengikuti symlinks dimana -r tidak akan.


17
2017-08-01 14:43



Untuk mencari file yang tersembunyi juga, jalankan shopt -s dotglob (ingat -s sebagai "set"). Hati-hati saat menghapus file itu. Jika Anda mengaktifkan dotglob, rm -r * menghapus semuanya di direktori saat ini, tetapi juga direktori di atasnya karena .. cocok. Untuk menonaktifkan dotglob, gunakan shopt -u dotglob ("tidak disetel"). Perubahan tersebut bersifat sementara, hanya berlaku untuk shell saat ini. - Lekensteyn
Saya lupa tentang ini. Apakah ada cara untuk menetapkannya untuk satu baris? sesuatu seperti shopt -s dotglob & <grep cmd> & shopt -y dotglob hanya lebih nyaman? Dengan cara ini kita tidak perlu khawatir tentang mengatur ulang itu - user606723
Juga, mungkin lebih mudah digunakan grep -Rin string . di sebagian besar kasus ini. Saya hanya menggunakan * karena tampaknya lebih alami. - user606723
jika Anda melakukan grep rekursif, maka Anda bisa mulai dari "." dari pada "*". tidak perlu dotglob. - Michał Šrajer
vote up ini, satu hal yang tidak disebutkan di manpage adalah R akan mengikuti tautan simbolis, r tidak - HVNSweeting


Jika Anda mau mencoba sesuatu yang baru, berikan ack sebuah tembakan. Perintah untuk secara rekursif mencari direktori saat ini untuk string aku s:

ack string

Instalasi cukup sederhana:

curl http://betterthangrep.com/ack-standalone > ~/bin/ack && chmod 0755 !#:3

(Asalkan Anda sudah punya direktori ~/bin dan itu lebih baik di Anda PATH.)


11
2017-08-01 15:09



Atau hanya apt-get install ack-grep (, dan tambahkan alias ack = ack-grep ke .bashrc Anda) - markijbema
Apa parameter terakhir untuk chmod perintah lakukan? Apakah mereka spesifik untuk chmod atau apakah mereka bash terkait (the !#:3 bagian)? - Elliott Darfink
@ElliottDarfink Itu menggunakan Bash fitur sejarah - ! adalah penunjuk acara. Mereka cukup kuat untuk menghindari pengulangan. !#:3 referensi token ketiga dari baris perintah sejauh ini, yaitu ~/bin/ack pada kasus ini. - Konrad Rudolph


Perintah rgrep didedikasikan untuk kebutuhan tersebut

Jika tidak tersedia, Anda bisa mendapatkannya seperti ini

mkdir -p ~/bin
cd ~/bin
wget http://sdjf.esmartdesign.com/files/rgrep
chmod +x rgrep

Anda dapat langsung mengatur opsi grep default Anda seperti yang dijelaskan di atas.

Saya menggunakan personnaly

[[  ${#args} -lt 5 && "${args//[[:space:]]/}" == "-i" ]] && args="-Hin"
args="${args:--Hns} --color=auto"

topik terkait: cara selalu menggunakan rgrep dengan warna


3
2018-01-02 13:58



rgrep disediakan oleh paket grep yang diinstal secara default di Ubuntu. - karel


Perbarui 2:

Baris perintah ini menggunakan find dan grep memperbaiki masalah:

$ find path_to_search_in -type f -exec grep -in searchString {} 2> /dev/null +

--color=<always or auto> untuk keluaran berwarna:

$ find path_to_search_in -type f \
            -exec grep --color=always -in searchString {} 2>/dev/null +

Contoh:

$ find /tmp/test/ -type f -exec grep --color=auto -in "Search string" {} 2>/dev/null +

Contoh dijalankan dalam snapshot di bawah ini: snap1


Pembaruan 1:

Anda dapat mencoba kode berikut; sebagai fungsi di Anda .bashrcatau .bash_aliases atau dalam skrip:

wherein () 
{ 
    for i in $(find "$1" -type f 2> /dev/null);
    do
        if grep --color=auto -i "$2" "$i" 2> /dev/null; then
            echo -e "\033[0;32mFound in: $i \033[0m\n";
        fi;
    done
}

Pemakaian: wherein /path/to/search/in/ searchkeyword

contoh:

$ wherein ~/Documents/ "hello world"

(Catatan: Seperti yang disarankan dalam komentar di bawah ini oleh @enzotib, ini tidak bekerja dengan file / direktori termasuk spasi di nama mereka.)


Pos asli

Untuk mencari string dan output hanya baris itu dengan string pencarian:

$ for i in $(find /path/of/target/directory -type f); do \
    grep -i "the string to look for" "$i"; done

misalnya.:

$ for i in $(find /usr/share/applications -type f); \
    do grep -i "web browser" "$i"; done

Untuk menampilkan nama file yang mengandung string pencarian:

$ for i in $(find /path/of/target/directory -type f); do \
    if grep -i "the string to look for" "$i" > /dev/null; then echo "$i"; fi; done;

misalnya.:

$ for i in $(find /usr/share/applications -type f); \
    do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \
    fi; done;

2
2018-01-25 11:11



Gagal pada nama file yang berisi spasi. Kegagalan ini disembunyikan oleh fakta bahwa stderr tidak ditampilkan. - enzotib
@enzotib terima kasih untuk menunjukkan itu .. itu masih belum terselesaikan untuk fungsi yang ditentukan .. Saya sudah menambahkan satu-liner lain .. - precise
Sekarang jawabannya mirip dengan @dmityugov. - enzotib
ya, tetapi dalam arti sebagian besar jawaban di halaman ini jika Anda memeriksa serupa dalam hal yang mereka gunakan grep, di samping itu menjadi bagian menggunakan find dengan grep... tetapi jika Anda ingin menerima switch dan tweak yang berbeda sebagai jawaban yang berbeda, mungkin saya akan cocok di sini juga ... atau apakah Anda berbeda? pembaruan terakhir melakukan apa yang saya inginkan dalam pencarian saya: nama file dengan garis dengan kunci pencarian dan baris no. terlalu :) dan output berwarna dan filter kesalahan untuk pembacaan yang lebih baik .. - precise


Saya melakukan ini menggunakan xargs, sebuah perintah yang sangat diremehkan

find ./ -type f -print0 | xargs -0 grep 'string_you_are_looking_for'

find ./ memberi Anda daftar rekursif dari semua file dalam folder saat ini kemudian Anda menyalurkannya ke xargs yang mengeksekusi perintah grep pada masing-masing file tersebut


1
2017-08-01 15:30



Menggunakan xargs tanpa -print0 opsi untuk find dan -0 opsi untuk xargs tidak lagi digunakan, akan gagal pada nama file yang berisi spasi. - enzotib
@enzotib Saya telah mengedit jawaban seperti yang Anda sarankan.- silakan tinjau dan jika perlu diedit dan dikoreksi, saya akan senang mengedit ulang oleh Anda. Terima kasih - αғsнιη
@KasiyA: sekarang sudah oke, menghapus downvote saya. - enzotib


Saya tahu ada banyak jawaban di sini, tapi ini alternatif jika Anda ingin menambahkan batasan lain saat mencari file:

find . -type f -exec grep --quiet string_to_look_for {} ';' -print

Ini berfungsi karena grep akan mengembalikan 0 jika menemukan hasil, 1 sebaliknya. Misalnya Anda dapat menemukan file berukuran 1 MB dan mengandung sesuatu:

find . -type f -exec grep --quiet string_to_look_for {} ';' -size 1M -print

Untuk beberapa persyaratan Anda mungkin ingin menggunakan bendera pengoptimal -O yang ada di GNU grep.


0
2018-03-11 13:56





Skrip (find-in-code) untuk mencari di C, kode CPP:

#!/bin/sh

find . \( -iname "*.c" -o -iname "*.cpp" -o -iname "*.h" \) -type f -print0 | xargs -0 grep --color -n "$1"

Menggunakan:

find-in-code "search string"

0
2018-06-11 16:49





grep (GNUatau BSD)

Kamu dapat memakai grep alat untuk mencari secara rekursif folder saat ini dengan -r parameter, seperti:

grep -r "pattern" .

catatan: -r - Subdirektori pencarian rekursif.

Untuk mencari dalam file tertentu, Anda dapat menggunakan sinting globbing seperti:

grep "class foo" **/*.c

Catatan: Dengan menggunakan Pilihan globbing (**), memindai semua file secara rekursif dengan ekstensi atau pola tertentu. Untuk mengaktifkan sintaks ini, jalankan: shopt -s globstar. Anda juga dapat menggunakan **/*.* untuk semua file (tidak termasuk yang tersembunyi dan tanpa ekstensi) atau pola lainnya.

Jika Anda memiliki kesalahan bahwa argumen Anda terlalu panjang, pertimbangkan mempersempit pencarian Anda, atau gunakan find syntax sebagai gantinya seperti:

find . -name "*.php" -execdir grep -nH --color=auto foo {} ';'

Atau gunakan ripgrep.

ripgrep

Jika Anda mengerjakan proyek yang lebih besar atau file besar, Anda harus menggunakannya ripgrep sebagai gantinya, seperti:

rg "pattern" .

Lihat dokumen, langkah instalasi atau kode sumber di Halaman proyek GitHub.

Ini jauh lebih cepat daripada alat lain seperti GNU/BSD  grep, ucg, ag, sift, ack, pt atau serupa, karena dibangun di atas Mesin regex karat yang menggunakan automata terbatas, SIMD dan optimasi literal yang agresif untuk membuat pencarian sangat cepat.

Ini mendukung pola mengabaikan yang ditentukan dalam .gitignore file, sehingga jalur file tunggal dapat dicocokkan dengan beberapa pola glob secara bersamaan.


Anda dapat menggunakan parameter umum seperti:

  • -i - Pencarian tidak sensitif.
  • -I - Abaikan file biner.
  • -w - Cari seluruh kata (berlawanan dengan pencocokan kata parsial).
  • -n - Tampilkan garis pertandingan Anda.
  • -C/--context (misalnya. -C5) - Meningkatkan konteks, sehingga Anda melihat kode sekitarnya.
  • --color=auto - Tandai teks yang cocok.
  • -H - Menampilkan nama file tempat teks ditemukan.
  • -c - Menampilkan hitungan garis yang cocok. Dapat digabungkan dengan -H.

0
2018-04-11 11:21