Antworten:
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
-lOption verpasst, bei der beide Befehle als gleich angesehen werden.
Pfeife grepineinander:
grep "string1" /path/to/files/* | grep "string2"
Hier ist der äquivalente ack- 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.
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.
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.
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.
-lOption, um die Dateinamen anstelle der Zeilen zurückzugeben. Er verwendet dann das Dollarzeichen oder die hinteren Anführungszeichen, um diese Liste alsFILEArgument 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.