Saya mencari cara untuk mencari file di mana dua contoh kata ada di file yang sama. Saya telah menggunakan yang berikut ini untuk melakukan pencarian saya hingga saat ini:
find . -exec grep -l "FIND ME" {} ;
Masalah yang saya hadapi adalah jika tidak ada tepat satu spasi antara "FIND" dan "ME", hasil pencarian tidak menghasilkan file. Bagaimana cara mengadaptasi string pencarian sebelumnya di mana kedua kata “FIND” dan “ME ada di file sebagai lawan dari “FIND ME”?
Saya menggunakan AIX.
Jawaban yang Diterima:
Dengan alat GNU:
find . -type f -exec grep -lZ FIND {} + | xargs -r0 grep -l ME
Anda dapat melakukan secara standar:
find . -type f -exec grep -q FIND {} ; -exec grep -l ME {} ;
Tapi itu akan berjalan hingga dua grep
s per file. Untuk menghindari menjalankan banyak grep
s dan masih portabel sambil tetap mengizinkan karakter apa pun dalam nama file, Anda dapat melakukan:
convert_to_xargs() {
sed "s/[[:blank:]"']/\\&/g" | awk '
{
if (NR > 1) {
printf "%s", line
if (!index($0, "//")) printf "\"
print ""
}
line = $0
}'
END { print line }'
}
export LC_ALL=C
find .//. -type f |
convert_to_xargs |
xargs grep -l FIND |
convert_to_xargs |
xargs grep -l ME
Idenya adalah untuk mengonversi output find
ke dalam format yang cocok untuk xargs (yang mengharapkan kosong (SPC/TAB/NL di C
locale, YMMV in other locales) daftar kata yang dipisahkan di mana tanda kutip tunggal, ganda, dan garis miring terbalik dapat menghindari titik kosong dan satu sama lain).
Umumnya Anda tidak dapat mem-post-proses output find -print
, karena memisahkan nama file dengan karakter baris baru dan tidak menghindari karakter baris baru yang ditemukan dalam nama file. Misalnya jika kita melihat:
./a
./b
Kami tidak tahu apakah itu satu file bernama b
dalam direktori bernama a<NL>.
atau jika itu adalah dua file a
dan b
di direktori saat ini.
Dengan menggunakan .//.
, karena //
tidak dapat muncul sebaliknya di jalur file sebagai output oleh find
(karena tidak ada direktori dengan nama kosong dan /
tidak diperbolehkan dalam nama file), kita tahu bahwa jika kita melihat baris yang berisi //
, maka itulah baris pertama dari nama file baru. Jadi kita bisa menggunakan awk
itu perintah untuk keluar dari semua karakter baris baru kecuali yang mendahului baris tersebut.
Jika kita ambil contoh di atas, find
akan menampilkan dalam kasus pertama (satu file):
.//a
./b
Awk mana yang lolos ke:
.//a
./b
Sehingga xargs
melihatnya sebagai satu argumen. Dan dalam kasus kedua (dua file):
.//a
.//b
Yang awk
akan pergi apa adanya, jadi xargs
melihat dua argumen.
Anda memerlukan LC_ALL=C
jadi sed
, awk
(dan beberapa implementasi xargs
) berfungsi untuk urutan byte yang berubah-ubah (meskipun itu tidak membentuk karakter yang valid di lokal pengguna), untuk menyederhanakan kosong definisi hanya untuk SPC dan TAB dan untuk menghindari masalah dengan interpretasi yang berbeda dari karakter yang pengkodeannya berisi pengkodean garis miring terbalik oleh utilitas yang berbeda.