Wie finde ich Dateien, die zwei Zeichenfolgen zusammen enthalten, unter Linux?

11

Ich möchte Dateien finden, die zwei Zeichenfolgen zusammen enthalten, zum Beispiel enthält die Datei beide string1und string2.

Ich möchte den vollständigen Pfad der Dateien in der Ausgabe. Ich möchte keine Warnungen "Erlaubnis verweigert" sehen.

alwbtc
quelle

Antworten:

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

das ist das gleiche wie

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

Edit: hier ist warum grep string1 /path/* | grep string2nicht was ich denke alwbtc will.

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

Nichts gefunden, aber Datei b enthält beide Zeichenfolgen.

Hier ist, was ich denke, dass alwbtc will

$ grep -l apples $(grep -l mangoes /tmp/*)
/tmp/b
RedGrittyBrick
quelle
1
Dies ist eine saubere Lösung und nützlicher als meine. Für diejenigen, die wissen wollen, was hier vor sich geht (ich habe ein bisschen gebraucht, um das herauszufinden), verwendet er die -lOption, um die Dateinamen anstelle der Zeilen zurückzugeben. Er verwendet dann das Dollarzeichen oder die hinteren Anführungszeichen, um diese Liste als FILEArgument an den zweiten Grep zu übergeben. Auf diese Weise kann der zweite Grep die gesamte gefundene Datei anstelle der einzelnen Zeilen wie in meiner Lösung durchsuchen.
embedded.kyle
Sie haben eine -lOption verpasst, bei der beide Befehle als gleich angesehen werden.
Pong
2

Pfeife grepineinander:

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

embedded.kyle
quelle
5
Wenn sich die beiden Zeichenfolgen in der Datei in unterschiedlichen Zeilen befinden, funktioniert dies nicht.
RedGrittyBrick
1
Ich wusste nicht, dass sie in derselben Zeile @RedGrittyBrick sein müssen
slhck
@slhck: Ich habe meine Antwort aktualisiert, um zu zeigen, was alwbtc meiner Meinung nach will und warum diese Antwort das nicht tut. Natürlich habe ich vielleicht falsch verstanden, was alwbtc will, und embedded.kyle hat es vielleicht richtig gemacht - ich vermute aber nicht.
RedGrittyBrick
1

Hier ist der äquivalente Befehl zu RedGrittyBricks Antwort :

ack string2 $(ack string1 -l)

Funktioniert genauso (außer ackstandardmäßig wird das aktuelle Verzeichnis rekursiv durchsucht). Der Inhalt innerhalb der $()Suche nach string1aber -lgibt nur die Dateinamen , wo die Zeichenfolge gefunden wurde. Sie werden dann als Argumente an den äußeren Befehl übergeben, dh, sie werden nur in dieser Dateiliste string2gesucht.

Congusbongus
quelle
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)

oder weniger redundant:

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

Dies funktioniert, wenn sich die Zeichenfolgen in verschiedenen Zeilen derselben Datei befinden, und vermeidet auch Fehlalarme, wenn ein Dateiname eine der Zeichenfolgen enthält.

user381521
quelle
0

Um auf die Lösung von @ RedGrittyBrick einzugehen, die ein Manko aufweist, wenn der Befehl unbeaufsichtigt ausgeführt wird, und um die Fehlerausgabe wie beabsichtigt zu unterdrücken und um Dateien rekursiv zu finden, die Sie möglicherweise in Betracht ziehen

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

-sOption Fehlermeldungen unterdrücken
-rOption ermöglicht Strings in beliebig verschachtelten Verzeichnissen suchen
!kombiniert mit && echo /dev/nullGarantien , dass der Befehl auf nicht hängen. Andernfalls gibt das inner grepGerät keine Ausgabe aus , wenn es keine findet, sodass outer grepes unbegrenzt auf die Eingabe wartet, nach der gesucht werden soll. Diese Lösung gibt /dev/nullin diesen Fällen so outer grepwird die Suche nach STRING1in /dev/nulldenen es angenommen hat , um nicht etwas zu finden.

Pong
quelle
0

Ich suchte nach einer erweiterbaren Möglichkeit, zwei oder mehr Saiten zu spielen, und fand Folgendes:

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

Der erste grep findet rekursiv die Namen der Dateien enthält , string1innerhalb path-to-files.

Die Ergebnisse werden weitergeleitet, in xargsdie ein oder mehrere grep-Befehle für diese Dateien ausgeführt werden string2.

Die Ergebnisse werden dann in einen anderen xargsBefehl für weitergeleitet string3- es ist dasselbe wie beim ersten xargsAufruf, aber es wird nach einer anderen Zeichenfolge gesucht.

Durch die Verwendung von xargswerden Probleme vermieden, bei denen so viele Ergebnisse vorliegen, dass die resultierende Befehlszeile aus der Verwendung von Back-Ticks zu lang ist.

Um die Warnungen zu vermeiden, können wir umleiten stderrzu /dev/null:

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

Es wird bei den nachfolgenden grep-Aufrufen nicht benötigt, da string1es bereits in der Datei gefunden wurde, sodass die Berechtigungen bekanntermaßen gut sind.

awatts
quelle