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 greps 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 findin 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 -printnicht 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 bin einem Verzeichnis handelt a<NL>.oder ob es sich um die beiden Dateien handelt aund 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 awkBefehl also verwenden, um alle Zeilenumbrüche außer denen, die diesen Zeilen vorangehen , zu maskieren.
Wenn wir das obige Beispiel nehmen, findwürde im ersten Fall (eine Datei) ausgegeben:
.//a
./b
Welcher awk entkommt:
.//a\
./b
Das xargssieht es als ein Argument. Und im zweiten Fall (zwei Dateien):
.//a
.//b
Was awkso belassen würde, xargssieht also zwei Argumente.