Mit GNU-Tools:
find . -type f -exec grep -lZ FIND {} + | xargs -r0 grep -l ME
Sie können standardmäßig Folgendes tun:
find . -type f -exec grep -q FIND {} \; -exec grep -l ME {} \;
Aber das würde zwei greps pro Datei ausführen. Um zu vermeiden, dass so viele grep
s ausgeführt werden und trotzdem portabel sind, während Zeichen in Dateinamen zulässig sind, können Sie Folgendes tun:
convert_to_xargs() {
sed "s/[[:blank:]\"\']/\\\\&/g" | awk '
{
if (NR > 1) {
printf "%s", line
if (!index($0, "//")) printf "\\"
print ""
}
line = $0
}'
END { print line }'
}
find .//. -type f |
convert_to_xargs |
xargs grep -l FIND |
convert_to_xargs |
xargs grep -l ME
Die Idee ist, die Ausgabe von find
in ein Format zu konvertieren, das für xargs geeignet ist (das ein Leerzeichen (SPC / TAB / NL, und die anderen Leerzeichen von Ihrem Gebietsschema mit einigen Implementierungen von xargs
), getrennte Liste von Wörtern, bei denen einfache, doppelte Anführungszeichen und umgekehrte Schrägstriche möglich sind Leerzeichen und einander entkommen).
Im Allgemeinen können Sie die Ausgabe von find -print
nicht nachbearbeiten, da die Dateinamen durch ein Zeilenumbruchzeichen getrennt werden und die in Dateinamen enthaltenen Zeilenumbrüche nicht ausgeblendet werden. Zum Beispiel wenn wir sehen:
./a
./b
Wir haben keine Möglichkeit herauszufinden, ob es sich um eine Datei b
in einem Verzeichnis handelt a<NL>.
oder ob es sich um die beiden Dateien handelt a
und b
.
Durch die Verwendung von .//.
, weil //
in einem Dateipfad nicht anders angezeigt werden kann als durch find
(weil es kein Verzeichnis mit einem leeren Namen gibt und /
in einem Dateinamen nicht zulässig ist), wissen wir, dass, wenn wir eine Zeile sehen, die enthält //
, das ist die erste Zeile eines neuen Dateinamens. Wir können diesen awk
Befehl also verwenden, um alle Zeilenumbrüche außer denen, die diesen Zeilen vorangehen , zu maskieren.
Wenn wir das obige Beispiel nehmen, find
würde im ersten Fall (eine Datei) ausgegeben:
.//a
./b
Welcher awk entkommt:
.//a\
./b
Das xargs
sieht es als ein Argument. Und im zweiten Fall (zwei Dateien):
.//a
.//b
Was awk
so belassen würde, xargs
sieht also zwei Argumente.