Bagaimana menemukan file yang mengandung dua string di Linux?

11

Saya ingin mencari file yang berisi dua string bersama, misalnya file berisi keduanya string1dan string2.

Saya ingin path lengkap file dalam output. Saya tidak ingin melihat peringatan "izin ditolak".

alwbtc
sumber

Jawaban:

15
grep -l string2 `grep -l string1 /path/*`

yang sama dengan

grep -l string2 $(grep -l string1 /path/*)

Sunting: di sini mengapa grep string1 /path/* | grep string2tidak melakukan apa yang saya pikir alwbtc inginkan.

$ cd /tmp
$ cat a
apples
oranges
bananas
$ cat b
apples
mangoes
lemons
$ cat c
mangoes
limes
pears
$ cd ~
$ grep apples /tmp/* | grep mangoes
$

Tidak ada yang ditemukan, tetapi file b berisi kedua string.

Inilah yang saya pikir alwbtc inginkan

$ grep -l apples $(grep -l mangoes /tmp/*)
/tmp/b
RedGrittyBrick
sumber
1
Ini adalah solusi yang rapi dan lebih bermanfaat daripada milik saya. Bagi mereka yang ingin tahu apa yang sedang terjadi di sini (butuh sedikit waktu untuk mencari tahu), dia menggunakan -lopsi untuk mengembalikan nama file, bukan baris. Dia kemudian menggunakan tanda dolar atau tanda kutip belakang untuk melewati daftar itu sebagai FILEargumen ke grep kedua. Ini memungkinkan grep kedua untuk mencari keseluruhan setiap file yang ditemukan alih-alih setiap baris seperti pada solusi saya.
embedded.kyle
Anda melewatkan -lopsi untuk kedua perintah agar dianggap sama.
pong
2

Pipa satu grepke yang lain:

grep "string1" /path/to/files/* | grep "string2"

tertanam.kyle
sumber
5
Jika dua string berada pada baris yang berbeda dalam file, ini tidak akan berfungsi.
RedGrittyBrick
1
Saya tidak tahu ada persyaratan bagi mereka untuk berada di baris yang sama @RedGrittyBrick
slhck
@ Slhck: Saya telah memperbarui jawaban saya untuk menunjukkan apa yang saya pikir alwbtc inginkan dan mengapa jawaban ini tidak melakukan itu. Tentu saja, saya mungkin telah salah mengerti apa yang diinginkan dan disematkan oleh alwbtc.kyle mungkin benar - saya kira tidak.
RedGrittyBrick
1

Inilah perintah setara dengan jawaban RedGrittyBrick :

ack string2 $(ack string1 -l)

Bekerja dengan cara yang sama (kecuali acksecara default mencari direktori saat ini secara rekursif). Konten dalam $()pencarian string1tetapi -lhanya menghasilkan nama file tempat string itu ditemukan. Mereka kemudian diteruskan sebagai argumen ke perintah luar, yang berarti string2dicari dalam daftar file saja.

congusbongus
sumber
0
comm -12 <(grep --fixed-strings --files-with-matches "STRING1" /path/to/files/* 2>/dev/null | sort) <(grep --fixed-strings --files-with-matches "STRING1" /path/to/files/* 2>/dev/null | sort)

atau kurang secara berlebihan:

search_files () { str="$1"; shift; grep -Fl "$str" "$@" 2>/dev/null | sort; }
comm -12 <(search_files "STRING1" /path/to/files/*) <(sf "STRING2" /path/to/files/*)

Ini akan berfungsi jika string berada pada baris yang berbeda dari file yang sama dan juga akan menghindari kesalahan positif jika nama file mengandung salah satu string.

pengguna381521
sumber
0

Untuk menguraikan solusi @ RedGrittyBrick yang memiliki kekurangan ketika menjalankan perintah tanpa pengawasan plus untuk menekan output kesalahan seperti yang dimaksudkan dan untuk menemukan file secara rekursif Anda dapat mempertimbangkan

grep -l 'STRING1' $(! grep -lrs 'STRING2' /absolute/path/to/search/dir && echo /dev/null)

-sopsi akan menekan
-ropsi pesan kesalahan memungkinkan untuk mencari string di direktori bersarang sewenang-wenang
!dikombinasikan dengan && echo /dev/nulljaminan bahwa perintah tidak akan menutup telepon. Jika tidak, jika inner greptidak menemukan file apa pun, maka tidak akan menghasilkan apa-apa sehingga outer grepmenunggu tak terbatas untuk input untuk dicari. Solusi ini menghasilkan /dev/nulldalam kasus ini sehingga outer grepakan mencari STRING1di /dev/nullmana itu seharusnya tidak menemukan apa pun.

pong
sumber
0

Saya sedang mencari cara yang bisa dikembangkan untuk melakukan 2 atau lebih string dan datang dengan ini:

grep -rl string1 path-to-files | xargs grep -l string2 | xargs grep -l string3

Grep pertama secara rekursif menemukan nama-nama file yang mengandung di string1dalamnya path-to-files.

Hasilnya disalurkan ke xargsmana menjalankan satu atau lebih perintah grep pada file-file itu string2.

Hasilnya kemudian disalurkan ke xargsperintah lain untuk string3- itu sama dengan xargspanggilan pertama , tetapi mencari string yang berbeda.

Penggunaan xargsakan menghindari masalah di mana ada begitu banyak hasil sehingga baris perintah yang dihasilkan dari penggunaan back-ticks terlalu lama.

Untuk menghindari peringatan, kami dapat mengalihkan stderrke /dev/null:

grep -rl string1 path-to-files  2>/dev/null | xargs grep -l string2

Itu tidak diperlukan pada panggilan grep berikutnya karena string1telah ditemukan di dalam file sehingga izin diketahui baik.

awatts
sumber