temukan dan gema nama file hanya dengan pola ditemukan

Jawaban:

23
find . -name '*.py' -exec grep something {} \; -print

akan mencetak nama file setelah baris yang cocok.

find . -name '*.py' -exec grep something /dev/null {} +

akan mencetak nama file di depan setiap baris yang cocok (kami menambahkan /dev/nulluntuk kasus di mana hanya ada satu file yang cocok karena greptidak mencetak nama file jika hanya melewati satu file untuk melihat. Implementasi GNU grepmemiliki -Hopsi untuk itu sebagai alternatif).

find . -name '*.py' -exec grep -l something {} +

hanya akan mencetak nama file dari file yang memiliki setidaknya satu baris yang cocok.

Untuk mencetak nama file sebelum baris yang cocok, Anda bisa menggunakan awk sebagai gantinya:

find . -name '*.py' -exec awk '
  FNR == 1 {filename_printed = 0}
  /something/ {
    if (!filename_printed) {
      print FILENAME
      filename_printed = 1
    }
    print
  }' {} +

Atau panggil grepdua kali untuk setiap file - meskipun itu akan kurang efisien karena akan menjalankan setidaknya satu grepperintah dan hingga dua untuk setiap file (dan membaca konten file dua kali):

find . -name '*.py' -exec grep -l something {} \; \
                    -exec grep something {} \;

Bagaimanapun, Anda tidak ingin mengulang-ulang output findseperti itu dan ingat untuk mengutip variabel Anda .

Jika Anda ingin menggunakan shell loop, dengan alat GNU:

find . -name '*.py' -exec grep -l --null something {} + |
   xargs -r0 sh -c '
     for file do
       printf "%s\n" "$file"
       grep something < "$file"
     done' sh

(juga berfungsi pada FreeBSD dan turunannya).

Stéphane Chazelas
sumber
6

Jika Anda menggunakan GNU grep, Anda dapat menggunakan -ratau --recursiveopsi untuk melakukan pencarian sederhana ini untuk Anda:

grep -r --include '*.py' -le "$regexp" ./ # for filenames only
grep -r --include '*.py' -He "$regexp" ./ # for filenames on each match

Anda hanya perlu findjika Anda membutuhkan lebih banyak predikat lanjut.

Toby Speight
sumber
1
Bergantung pada versi GNU grep, grepmungkin atau mungkin tidak melihat ke dalam symlink atau melintasi symlink ke direktori. Anda juga dapat menemukan beberapa variasi dalam penanganan jenis file non-reguler lainnya.
Stéphane Chazelas
5

Anda dapat memberitahu grep untuk memasukkan nama file dalam output. Jadi jika ada kecocokan akan ditampilkan di konsol; jika tidak ada kecocokan dalam suatu file, tidak ada baris yang akan dicetak untuk file itu.

find . -name "*.py" | xargs grep -n -H something

Dari man grep:

-H       Always print filename headers with output lines
-n, --line-number
         Each output line is preceded by its relative line number in the file, starting at line 1.  The line number counter is reset for each file processed.
         This option is ignored if -c, -L, -l, or -q is specified.

Jika file Anda mungkin memiliki nama dengan spasi di dalamnya, Anda harus mengganti pipa untuk menggunakan NUL Characters sebagai pemisah. Perintah lengkap sekarang akan terlihat seperti ini:

find . -name "*.py" -print0 | xargs -0 grep -n -H something
rollstuhlfahrer
sumber
1

Anda dapat mencoba sesuatu seperti:

find . -name "*.py:" -exec grep -l {} \;

Perintah exec grep ini untuk setiap file, ditemukan oleh perintah find dan fitur perintah find standarnya

Romeo Ninov
sumber
1

Gunakan -largumennya.

for file in `find . -name "*.py"`; do grep -l something $file && grep something $file; done

Penggunaan yang lebih menemukan adalah:

for file in $(find . -name '*.py' -exec grep -l something '{}' +); do echo "$file"; grep something $file; done
kmkaplan
sumber
1

Ada grepalternatif yang secara default menampilkan hasilnya dalam format yang Anda inginkan. 2 yang paling populer yang saya tahu adalah ag(alias "pencari perak") dan ack. agdiiklankan sebagai alternatif yang lebih cepat untuk ack.

$ ag '^\w+\s*\w+\(' ~/build/i3/src
build/i3/src/display_version.c
58:void display_running_version(void) {

build/i3/src/load_layout.c
42:static TAILQ_HEAD(focus_mappings_head, focus_mapping) focus_mappings =
518:json_content_t json_determine_content(const char *filename) {
575:void tree_append_json(Con *con, const char *filename, char **errormsg) {

build/i3/src/x.c
64:CIRCLEQ_HEAD(state_head, con_state) state_head =
67:CIRCLEQ_HEAD(old_state_head, con_state) old_state_head =
70:TAILQ_HEAD(initial_mapping_head, con_state) initial_mapping_head =
97:void x_con_init(Con *con, uint16_t depth) {
...

Saya tidak bisa menunjukkan Anda di sini, tetapi hasilnya berwarna rapi. Saya mendapatkan nama file berwarna hijau zaitun, nomor baris berwarna kuning emas, dan potongan yang cocok di setiap baris berwarna merah darah. Namun warna dapat disesuaikan.

JoL
sumber