Manakah yang lebih efisien untuk menemukan file mana di seluruh sistem file yang berisi string: grep rekursif atau temukan dengan grep dalam pernyataan exec? Saya menganggap menemukan akan lebih efisien karena Anda setidaknya dapat melakukan beberapa penyaringan jika Anda tahu ekstensi file atau regex yang cocok dengan nama file, tetapi ketika Anda hanya tahu -type f
mana yang lebih baik? GNU grep 2.6.3; find (GNU findutils) 4.4.2
Contoh:
grep -r -i 'the brown dog' /
find / -type f -exec grep -i 'the brown dog' {} \;
-exec {} +
formulir akan melakukan lebih sedikit fork, jadi harus lebih cepat daripada-exec {} \;
. Anda mungkin perlu menambahkan-H
(atau-h
) kegrep
opsi untuk mendapatkan hasil yang sama persis.-r
opsigrep
untuk yang keduaJawaban:
Saya tidak yakin:
benar-benar yang Anda maksudkan. Itu berarti grep secara rekursif di semua file dan dirs non-tersembunyi
/
(tapi masih mencari di dalam file dan dirs tersembunyi di dalamnya).Anggap Anda maksud:
Beberapa hal yang perlu diperhatikan:
grep
implementasi mendukung-r
. Dan di antara mereka yang melakukannya, perilaku berbeda: beberapa mengikuti symlink ke direktori ketika melintasi pohon direktori (yang berarti Anda mungkin berakhir mencari beberapa kali dalam file yang sama atau bahkan berjalan dalam loop tak terbatas), beberapa tidak akan. Beberapa akan mencari di dalam file perangkat (dan itu akan membutuhkan beberapa waktu/dev/zero
misalnya) atau pipa atau file biner ..., beberapa tidak.grep
mulai mencari ke dalam file begitu menemukan mereka. Tetapi sementara itu terlihat dalam sebuah file, itu tidak lagi mencari lebih banyak file untuk dicari (yang mungkin sama baiknya dalam kebanyakan kasus)Anda:
(menghapus
-r
yang tidak masuk akal di sini) sangat tidak efisien karena Anda menjalankan satugrep
per file.;
seharusnya hanya digunakan untuk perintah yang hanya menerima satu argumen. Terlebih lagi di sini, karenagrep
hanya terlihat dalam satu file, itu tidak akan mencetak nama file, sehingga Anda tidak akan tahu di mana pertandingannya.Anda tidak mencari di dalam file perangkat, pipa, symlink ..., Anda tidak mengikuti symlink, tetapi Anda masih berpotensi mencari hal-hal seperti di dalamnya
/proc/mem
.akan jauh lebih baik karena
grep
perintah sesedikit mungkin akan dijalankan. Anda akan mendapatkan nama file kecuali proses terakhir hanya memiliki satu file. Untuk itu lebih baik menggunakan:atau dengan GNU
grep
:Perhatikan bahwa
grep
tidak akan dimulai sampaifind
menemukan cukup file untuk dikunyah, sehingga akan ada beberapa penundaan awal. Danfind
tidak akan melanjutkan mencari lebih banyak file sampai sebelumnyagrep
telah kembali. Mengalokasikan dan melewati daftar file besar memiliki beberapa dampak (mungkin dapat diabaikan), jadi semuanya mungkin akan kurang efisien daripadagrep -r
yang tidak mengikuti symlink atau melihat ke dalam perangkat.Dengan alat GNU:
Seperti di atas, beberapa
grep
contoh mungkin akan dijalankan, tetapifind
akan terus mencari lebih banyak file sementaragrep
doa pertama mencari di dalam batch pertama. Itu mungkin atau mungkin tidak menguntungkan. Misalnya, dengan data yang disimpan pada hard drive rotasi,find
dangrep
mengakses data yang disimpan di lokasi yang berbeda pada disk akan memperlambat throughput disk dengan menyebabkan kepala disk bergerak terus-menerus. Dalam pengaturan RAID (di manafind
dangrep
dapat mengakses disk yang berbeda) atau pada SSD, yang mungkin membuat perbedaan positif.Dalam pengaturan RAID, menjalankan beberapa pemanggilan serentak
grep
juga dapat meningkatkan banyak hal. Masih dengan alat GNU pada penyimpanan RAID1 dengan 3 disk,dapat meningkatkan kinerja secara signifikan. Namun perlu dicatat bahwa yang kedua
grep
hanya akan dimulai setelah file yang cukup telah ditemukan untuk mengisigrep
perintah pertama . Anda dapat menambahkan-n
opsi agar halxargs
itu terjadi lebih cepat (dan memberikan lebih sedikit file pergrep
permintaan).Juga perhatikan bahwa jika Anda mengarahkan
xargs
output ke apa pun selain perangkat terminal, makagreps
s akan mulai buffering output mereka yang berarti bahwa output dari merekagrep
mungkin akan disisipkan secara tidak benar. Anda harus menggunakanstdbuf -oL
(jika tersedia seperti pada GNU atau FreeBSD) pada mereka untuk mengatasinya (Anda mungkin masih memiliki masalah dengan garis yang sangat panjang (biasanya> 4KiB)) atau minta masing-masing menuliskan output mereka dalam file terpisah dan menggabungkannya semua pada akhirnya.Di sini, string yang Anda cari sudah diperbaiki (bukan regexp) jadi menggunakan
-F
opsi mungkin akan membuat perbedaan (tidak mungkin karenagrep
implementasi tahu cara mengoptimalkannya).Hal lain yang dapat membuat perbedaan besar adalah memperbaiki lokal ke C jika Anda berada di lokal multi-byte:
Untuk menghindari mencari ke dalam
/proc
,/sys
..., gunakan-xdev
dan tentukan sistem file yang ingin Anda cari:Atau pangkas jalur yang ingin Anda kecualikan secara eksplisit:
sumber
-exec
predikat di halaman manual SolarisJika
*
dalamgrep
panggilan tidak penting bagi Anda maka yang pertama harus lebih efisien karena hanya satu contoh darigrep
dimulai, dan garpu tidak bebas. Dalam kebanyakan kasus akan lebih cepat bahkan dengan*
tetapi dalam kasus tepi penyortiran bisa membalikkan itu.Mungkin ada
find
-grep
struktur lain yang bekerja lebih baik terutama dengan banyak file kecil. Membaca entri dan inode file dalam jumlah besar sekaligus dapat memberikan peningkatan kinerja pada media yang berputar.Tapi mari kita lihat statistik syscall:
Temukan
grep saja
sumber
-r
benderagrep
saat menggunakanfind
. Anda dapat melihatnya berulang kali mencari file yang sama dengan membandingkan jumlahopen
yang terjadi.-r
seharusnya tidak berbahaya karena-type f
jaminan tidak ada argumen yang direktori. Beberapaopen()
s lebih cenderung ke file lain yang dibuka olehgrep
pada setiap doa (perpustakaan, data lokalisasi ...) (terima kasih atas hasil edit pada jawaban saya btw)Jika Anda menggunakan SSD dan mencari waktu dapat diabaikan, Anda dapat menggunakan GNU parallel:
Ini akan menjalankan hingga 8 proses grep secara bersamaan berdasarkan apa yang
find
ditemukan.Ini akan meremukkan drive hard disk, tetapi SSD harus mengatasinya dengan cukup baik.
sumber
Satu hal lagi yang perlu dipertimbangkan dalam hal ini adalah sebagai berikut.
Apakah ada direktori yang grep harus secara rekursif melewati berisi lebih banyak file daripada pengaturan nofile sistem Anda ? (mis. jumlah pegangan file terbuka, standarnya adalah 1024 pada kebanyakan distro linux)
Jika demikian, maka mencari pasti cara untuk pergi karena versi grep tertentu akan membom dengan daftar Argument error terlalu lama ketika hits direktori dengan lebih banyak file daripada pengaturan menangani file terbuka maksimum.
Hanya 2 my saya.
sumber
grep
mengebom? Setidaknya dengan GNU grep jika Anda memberikan path dengan trailing/
dan menggunakannya-R
hanya akan beralih melalui direktori. The shell tidak akan memperluas apa pun kecuali Anda memberikan shell-gumpalan. Jadi dalam contoh yang diberikan (/*
) hanya isi/
materi, bukan dari subfolder yang hanya akan disebutkan olehgrep
, tidak disahkan sebagai argumen dari shell.