Temukan pipa ke grep -v

18

Saya mencoba menemukan semua file yang berjenis tertentu dan tidak mengandung string tertentu. Saya mencoba untuk menyelesaikannya dengan mem-piping find ke grep -v

contoh:

find -type f -name '*.java' | xargs grep -v "something something"

Ini sepertinya tidak berhasil. Tampaknya hanya mengembalikan semua file yang ditemukan oleh perintah find. Apa yang saya coba lakukan pada dasarnya adalah menemukan semua file .java yang cocok dengan nama file tertentu (mis. Diakhiri dengan 'Pb' seperti pada SessionPb.java) dan yang tidak memiliki 'extends SomethingSomething "di dalamnya.

Kecurigaan saya adalah saya melakukan kesalahan. Jadi bagaimana seharusnya perintah itu?

Hyangelo
sumber
Anda dapat menambahkan apa yang membuat Anda berpikir itu tidak berhasil. mungkin ekspresi grep Anda terlalu eksplisit? membutuhkan '-i' untuk ketidakpekaan kasus? Lihat jawaban saya di bawah juga ...
lornix

Jawaban:

21

Tidak perlu di xargssini. Juga Anda perlu menggunakan grepdengan -Lpilihan (file tanpa pertandingan), menyebabkan jika tidak maka akan menampilkan isi file bukan namanya, seperti dalam contoh Anda.

find . -type f -iname "*.java" -exec grep -L "something somethin" {} \+
buru-buru
sumber
1
-Lsudah melakukan negosiasi, karena itu artinya files _without_ match. Karena itu Anda tidak perlu -vopsi di sini.
buru
3
tidak dengan + ekstra di akhir.
lynxlynxlynx
2
@ user946850 setiap kali saya menulis find -exec \+seseorang menulis kepada saya bahwa jauh lebih baik menggunakan xargs. mengapa tidak ada yang terlihat seperti pria sebelum menulis komentar? (:
buru
5
@ user946850 -exec ... {} \+tidak setara dengan xargs. Silakan baca dokumentasi findutils! (Saya bekerja cukup keras untuk itu!)
James Youngman
2
@ user946850 ya. Salah satu perbedaannya adalah bahwa (secara default) xargsmemproses inputnya dan memisahkan argumen pada spasi putih. Kutipan juga spesial (secara default) untuk xargs. Tak satu pun dari hal-hal ini berlaku untuk -exec ... {} +. Versi lama yang xargsdigunakan untuk mempertimbangkan garis bawah sebagai indikator EOF, tetapi ini bukan masalahnya lagi.
James Youngman
7

Anda hampir mendapatkannya benar-benar ...

find . -type f -iname "*.java" -print0 | xargs -0 grep -v "something something"

Titik '.' mengatakan mulai dari sini. (milikmu menyiratkannya .. tapi jangan pernah berasumsi).

-iname menggunakan pencarian case-insensitive, untuk jaga-jaga (atau hanya in-case).
-print0 mengirim nama file ke xargs dengan karakter trailing \ x00, yang mencegah masalah dengan nama file memiliki spasi di dalamnya.

'-0' pada xargs mengatakan mengharapkan nama file diakhiri dengan \ x00 alih-alih pengembalian.

dan perintah grep Anda ...

Cukup banyak mengerti.


EDIT ::

Dari pembaruan Anda:

find . -type f -iname "*pb.java" -print0 | xargs -0 grep -iL "something"

harus membantu. (Ditambahkan -L dari jawaban @ rush, kerja bagus)

Saya mendapat ide bahwa grep Anda membutuhkan opsi '-i', atau menjadi kurang eksplisit.

Coba perintah di bagian ... apakah ini menghasilkan nama file yang tampaknya tepat?

find . -type f -iname "*pb.java"

Jika demikian, maka masalah Anda kemungkinan adalah pola pencarian grep Anda tidak cocok (kesalahan ejaan? Itu terjadi!), Atau tidak ada kecocokan.

Kasus terburuk absolut:

grep -riL "something" *

akan melakukan banyak pekerjaan BANYAK mencari semuanya, tetapi harus memberi Anda beberapa output.

lornix
sumber
Saya mencoba modifikasi Anda dan saya masih belum mendapatkan hasil yang saya harapkan. Saya akan mencoba memperbarui pertanyaan untuk membuatnya lebih jelas.
Hyangelo
Jika penulis pertanyaan hanya ingin mencari nama file, bukankah grep harus 'grep -l -v'?
Bruce Ediger
dia sedang mencari konten spesifik dalam file * .java
lornix
xargs -0 grep -v "something something"harus xargs -0 grep -v "something something" /dev/nulljika tidak, anda akan mendapatkan hasil yang aneh ketika menemukan tidak menghasilkan file yang cocok.
James Youngman
{Grin} yeah, di suatu tempat di sana logikanya menjadi berbulu. Tidak ada yang seperti tes beberapa logika palsu terbalik untuk membuat kepala Anda sakit.
lornix
4

Komputer menjadi komputer: komputer melakukan apa yang Anda perintahkan, bukan apa yang Anda inginkan.

grep -v "something something"mencetak semua garis yang tidak mengandung something something. Misalnya, ia mencetak dua baris di antara tiga berikut:

hello world
this is something something
something else

Untuk mencetak file yang tidak mengandung di extends SomethingSomethingmana pun, gunakan -Lopsi:

grep -L -E 'extends[[:space:]]+SomethingSomething' FILENAME…

Beberapa versi grep tidak memiliki -Lopsi (tidak ditentukan oleh POSIX ). Jika milik Anda tidak, mintalah ia mencetak apa-apa, dan gunakan kode pengembalian untuk membuat shell panggilan melakukan apa pun yang seharusnya dilakukan.

grep -q -E 'extends[[:space:]]+SomethingSomething' FILENAME ||
echo "$FILENAME"

Atau, gunakan awk.

awk '
    FNR == 1 && NR != 1 && !found { print fn }
    FNR == 1 { fn = FILENAME; found = 0; }
    /extends[[:space:]]+SomethingSomething/ { found = 1 }
    END { if (fn != "" && !found) print fn }
'

Di Linux atau Cygwin (atau sistem lain dengan GNU grep), Anda tidak perlu menggunakan find, karena grepmampu berulang.

grep -R --include='*.java' -L -E 'extends[[:space:]]+SomethingSomething'

Jika shell Anda adalah ksh atau bash atau zsh, Anda dapat membuat shell melakukan pencocokan nama file. Pada bash, jalankan set -o globstarterlebih dahulu (Anda dapat menempatkan ini di Anda ~/.bashrc).

grep -L -E 'extends[[:space:]]+SomethingSomething' **/*.java
Gilles 'SANGAT berhenti menjadi jahat'
sumber
Wow ini bahkan lebih baik. Saya menggunakan 'extends (/ s) + SomethingSomething' yang sepertinya berfungsi sejauh yang saya tahu. Apakah ada perbedaan dengan sintaks ini dengan yang ditentukan dalam versi Extended RegEx?
Hyangelo
@Hyangelo \sadalah ekstensi grep GNU, yang saya pikir identik dengan [[:space:]].
Gilles 'SO- stop being evil'