Nehmen wir an, ich möchte alle .txt
-Dateien finden und nach einer Zeichenfolge suchen. Ich würde Folgendes tun:
find ./ -type f -name "*.txt" -exec egrep -iH "something" "{}" \;
Was ist, wenn ich eine komplexere Filterung wie folgt durchführen möchte:
egrep something file.txt | egrep somethingelse | egrep other
Inside find -exec? (oder ähnliches)
Bitte denken Sie daran, dass ich nach einer Lösung suche, die ich bei Bedarf einfach eingeben kann. Ich weiß, dass dies mit ein paar Zeilen unter Verwendung eines Shell-Skripts möglich ist, aber das ist nicht das, wonach ich suche.
Antwort
Wenn Sie dies innerhalb von find tun müssen, müssen Sie eine Shell aufrufen:
find ./ -type f -name "*.txt" -exec sh -c "grep -EiH something "$1" | grep -E somethingelse | grep -E other" sh {} \;
Andere Alternativen umfassen die Verwendung von xargs
stattdessen:
find ./ -type f -name "*.txt" | xargs -I{} grep -EiH something {} | grep -EiH somethingelse | grep -EiH other
Or. En , viel sicherer für beliebige Dateinamen (vorausgesetzt, Ihre find
unterstützt -print0
):
find ./ -type f -name "*.txt" -print0 | xargs -0 grep -EiH something {} | grep -Ei somethingelse | grep -Ei other
Oder Sie können stattdessen einfach eine Shell-Schleife verwenden:
find ./ -type f -name "*.txt" -print0 | while IFS= read -d "" file; do grep -Ei something "$file" | grep -Ei somethingelse | grep -Ei other done
Kommentare
- Der erste ist genau das, wonach ich gesucht habe. Extrem einfach und klein genug, um je nach meinen Bedürfnissen zu tippen. Danke.
- … und
xargs
können auch alsxargs -I {} sh -c '...' sh {}
verwendet werden, wenn man möchte (es macht Es ist möglich, parallele Jobs mit-P
auszuführen, wenn dies gewünscht wird.
Antwort
Bearbeiten: Diese Antwort ist nicht bevorzugt , wird jedoch hier zum Vergleich und zur Veranschaulichung potenziell gefährlicher Fallstricke belassen in Bash-Skripten.
Sie können bash
(oder eine andere Shell) als Ihren -exec
-Befehl eingeben:
find -type -f -name "*.txt" -exec bash -c "egrep -iH something "{}" | egrep somethingelse | egrep other" \;
Einer der Nachteile dieser Vorgehensweise besteht darin, dass mehr erstellt wird Potenzial für verschachtelte Anführungszeichenprobleme, wenn Ihre Befehle komplexer werden. Wenn Sie dies vermeiden möchten, können Sie es in eine for
-Schleife aufteilen:
for i in $(find -type -f -name "*.txt"); do if egrep -iH something "$i" | egrep somethingelse | egrep other; then echo "Found something: $i" fi done
Kommentare
- Der erste ist genau das, wonach ich gesucht habe. Extrem einfach und klein genug, um je nach meinen Bedürfnissen zu tippen. Vielen Dank.
- Diese
for
-Schleife ist eine sehr schlechte Idee. Auch bekannt als bash pitfall # 1 . - Diese
"{}"
in Ihrem ersten Befehl kann sogar zur Code-Injektion führen. Stellen Sie sich vor, Sie haben Dateien von mir und es gibt ' eine Datei mit dem wörtlichen Namen" & rm -rf ~ & : ".txt
. Zum Glück für Sie ist-type -f
ungültig, es hat nur Ihr Home-Verzeichnis gespeichert. Beheben Sie den Tippfehler und versuchen Sie es erneut. 🙂 terdon hat es richtig gemacht:find … -exec sh -c '… "$1" …' foo {} \;
. - Danke für die Information! Ja, die
-type -f
ist ein Tippfehler, den ich ständig mache, wenn ichfind
verwende, und ich habe nicht ' merke es nicht in meiner Antwort. Hoppla. Die Antwort von terdon ' ist besser, aber ich ' lasse dies zu Vergleichszwecken. - @terdon: tx zum Verweisen auf die Seite mywiki.wooledge.org. ' ist schön, wenn ein paar Allgemeinmediziner an einem Ort zusammengefasst sind.