Come trovare file contenenti due stringhe insieme in Linux?


11

Voglio trovare file contenenti due stringhe insieme, ad esempio il file contiene sia string1e string2.

Voglio il percorso completo dei file in uscita. Non voglio vedere gli avvisi "permesso negato".

Risposte:


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

che è lo stesso di

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

Modifica: ecco perché grep string1 /path/* | grep string2non fa quello che penso che Alwbtc vuole.

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

Non è stato trovato nulla, ma il file b contiene entrambe le stringhe.

Ecco cosa penso che alwbtc voglia

$ grep -l apples $(grep -l mangoes /tmp/*)
/tmp/b

1
Questa è una soluzione pulita e più utile della mia. Per coloro che vogliono sapere cosa sta succedendo qui (mi ci è voluto un po 'per capire), sta usando l' -lopzione per restituire i nomi dei file invece delle righe. Quindi usa il segno del dollaro o le virgolette posteriori per passare quella lista come FILEargomento nel secondo grep. Ciò consente al secondo grep di cercare tutti i file trovati anziché le singole righe come nella mia soluzione.
embedded.kyle,

Hai perso -lun'opzione per entrambi i comandi da considerare uguali.
pong

2

Pipe uno grepnell'altro:

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


5
Se le due stringhe si trovano su righe diverse nel file, questo non funzionerà.
RedGrittyBrick,

1
Non sapevo che ci fosse un requisito per loro di essere nella stessa linea @RedGrittyBrick
slhck

@slhck: ho aggiornato la mia risposta per mostrare cosa penso che alwbtc voglia e perché questa risposta non lo faccia. Certo, potrei aver frainteso ciò che vuole alwbtc e embedded.kyle potrebbe averlo fatto bene - sospetto di no.
RedGrittyBrick,

1

Ecco il comando equivalente alla risposta di RedGrittyBrick :

ack string2 $(ack string1 -l)

Funziona allo stesso modo (tranne che ackper impostazione predefinita cerca ricorsivamente la directory corrente). I contenuti all'interno delle $()ricerche, string1ma -lrestituiscono solo i nomi dei file in cui è stata trovata quella stringa. Vengono quindi passati come argomenti al comando esterno, il che significa che string2viene cercato solo all'interno di quell'elenco di file.


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)

o meno ridondante:

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/*)

Ciò funzionerà se le stringhe si trovano su righe diverse dello stesso file ed eviterà anche i falsi positivi se un nome file contiene una delle stringhe.


0

Per approfondire la soluzione di @ RedGrittyBrick che presenta un difetto durante l'esecuzione del comando incustodito e di sopprimere l'output degli errori come previsto e di trovare i file in modo ricorsivo, è possibile prendere in considerazione

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

-sL'opzione sopprimerà i messaggi di errore L'
-ropzione consente di cercare stringhe in directory arbitrariamente nidificate
!insieme a && echo /dev/nullgaranzie che il comando non si bloccherà. Altrimenti, se inner grepnon trova alcun file, non verrà emesso nulla in modo tale outer grepche attenderà indefinitamente l'input per la ricerca. Questo uscite soluzione /dev/nullin questi casi in modo outer grepcercheranno STRING1in /dev/nullcui si suppone che non trovare nulla.


0

Stavo cercando un modo estensibile per fare 2 o più stringhe e ho trovato questo:

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

Il primo grep trova ricorsivamente i nomi dei file che contengono string1all'interno path-to-files.

I risultati vengono convogliati in xargscui viene eseguito uno o più comandi grep su tali file string2.

I risultati vengono quindi reindirizzati a un altro xargscomando per string3: è lo stesso della prima xargschiamata, ma cerca una stringa diversa.

L'uso di xargseviterà problemi in cui vi sono così tanti risultati che la riga di comando risultante dall'uso di back-tick è troppo lunga.

Per evitare gli avvisi possiamo reindirizzare stderra /dev/null:

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

Non è necessario nelle successive chiamate grep perché string1è già stato trovato all'interno del file, quindi le autorizzazioni sono note per essere buone.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.