Perpipaan dari find ke grep

8

Apa yang saya coba lakukan?

Tulis perintah yang mencari file apa pun yang tidak diperlukan oleh file lain di proyek saya.

Apa yang sudah saya coba?

Saya menggunakan finduntuk mendapatkan daftar nama file. Sekarang saya ingin menggunakan nama file sebagai string pencarian (bukan file untuk mencari).

Saya menggunakan find server/lib -type f -exec basename {} \; | cut -f 1 -d '.'untuk mendapatkan daftar nama file dan menghapus ekstensi file.

Sekarang saya tahu bahwa inilah grep -R --exclude-dir=node_modules <search-string> . -lyang ingin saya sambungkan ke setiap nama file, tetapi saya tidak tahu bagaimana meneruskannya sebagai <search-string>argumen.


Info lain

Saya juga samar-samar menyadari bahwa mem-piping ke ini grepmungkin melewati seluruh hasil dari find(seluruh daftar file) yang saya jelas tidak ingin melakukannya jika itu yang akan saya lakukan maka katakan padaku.

Juga, (walaupun ini mungkin tidak dalam lingkup pertanyaan ini) karena saya menggunakan ini sebagai cara untuk menemukan nama file yang grepgagal menemukan apa pun, saran untuk mendapatkan output semacam ini akan sangat dihargai

> <the-command>

filename1
server/lib/foo.js # where these are the list of files in which it appears
test/lib/foo.js

filename2
Not Found! #where `filename2` wasn't found anywhere (obviously)
Simon Legg
sumber

Jawaban:

2

Jawaban singkat:

Jika Anda hanya ingin meneruskan banyak baris sebagai argumen ke perintah lain, xargsadalah teman Anda - dalam hal ini, karena Anda meletakkannya di tengah-tengah perintah, Anda akan ingin menggunakan -I {}bendera. Ini ditetapkan {}sebagai placeholder sehingga Anda dapat menempatkan di mana saja (Anda dapat menetapkan placeholder Anda sendiri, tetapi saya biasanya tetap menggunakannya {}karena tidak akan salah untuk banyak hal lainnya.

Menyatukan semuanya (dengan asumsi perintah yang Anda berikan lakukan apa yang Anda pikir mereka lakukan!):

find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' | xargs -I {} grep -R --exclude-dir=node_modules {} . -l

Jawaban panjang

Ok, jadi kita mungkin bisa mengambil ini lebih lanjut Katakanlah Anda menginginkan format yang Anda sebutkan sebelumnya - Anda bisa xargsmelakukannya sh -csehingga Anda dapat membuat perintah:

find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' | xargs -I {} sh -c "echo {}; grep -R --exclude-dir=node_modules {} . -l"

Menjalankan ini di komputer saya, sepertinya ini memberi Anda file di mana file itu ditemukan. Otak saya lelah, jadi alih-alih membungkusnya dengan skrip yang bagus (yang sebenarnya harus Anda lakukan ketika oneliners mulai menjadi keriput, dan gunakan https://www.shellcheck.net/ saat Anda sedang melakukannya) Anda bisa miliki hack yang mengerikan ini, yang (saya pikir) akan memberi Anda output yang Anda cari:

find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' | xargs -I {} sh -c "echo {}; grep -R --exclude-dir=node_modules {} . -l && printf \"\n\" || printf \"Not found\n\n\""

Paku
sumber
Terima kasih banyak, ya xargs -I {}apa yang saya cari.
Simon Legg
6

Dengan zsh:

projects=(server/lib/**/*(D.:t:r))
grep -rFl --exclude-dir=node_modules -e${(u)^projects} .
  • **/globbing rekursif. Fitur yang diperkenalkan zshpada awal tahun 90an.
  • (D.:t:r)adalah glob qualifier, zshfitur-spesifik yang memungkinkan memilih file menggunakan atribut selain nama, atau mengubah penyortiran atau melakukan modifikasi pada file yang ditemukan.
  • D: sertakan dot-file dan lintasi dot-dir seperti yang findakan terjadi. Kemungkinan besar, Anda ingin melepasnya.
  • .: hanya file biasa (seperti -type fdi find)
  • :t, :r: pengubah riwayat seperti di csh/ bashtapi di sini diterapkan ke file globbed. :tuntuk bagian ekor (nama depan), :runtuk nama akar (ekstensi dihapus).
  • x${^array}mendistribusikan elemen seperti rc's x^$arrayatau fish' s x$arrayakan melakukan. Misalnya jika $arrayadalah ( 1, 2). Itu menjadi x1 x2.
  • ${(u)array}(untuk unique), hapus duplikat ( (u)menjadi bendera ekspansi parameter).

Untuk daftar file yang tidak mengandung string, ganti -ldengan -L( dengan asumsi GNU grep, tetapi Anda sudah menggunakan opsi spesifik GNU di sini). -Fadalah untuk pencarian string tetap (karena Anda mungkin tidak ingin nama-nama proyek diperlakukan sebagai regexps). Anda mungkin juga ingin melemparkan -wopsi untuk grepuntuk pencocokan kata sehingga footidak cocok foobarmisalnya (masih akan tetap cocok foo-bar).

Stéphane Chazelas
sumber
Terima kasih yang luar biasa untuk ini dan penjelasannya, saya tidak sadar projects=(server/lib/**/*(D.:t:r))memproduksi array seperti itu di zsh. Namun saya sekarang perlu daftar file di mana grepgagal menemukan apa pun. Saya kira saya perlu menangkap kode keluar 0 / false?
Simon Legg
@Simon, lihat bagian tentang -Ldi akhir jawaban
Stéphane Chazelas
Ya, saya melihat itu. -lmemberi tahu saya di mana hasil pencarian itu dan -Lmemberi tahu saya di mana itu tidak ditemukan. Tapi saya ingin tahu daftar istilah pencarian yang tidak ditemukan di mana pun dan bukan di mana mereka / tidak ditemukan
Simon Legg