Supponiamo che io voglia trovare tutti i file .txt
e cercare qualche stringa. Farei:
find ./ -type f -name "*.txt" -exec egrep -iH "something" "{}" \;
E se volessi applicare un filtro più complesso, come questo:
egrep something file.txt | egrep somethingelse | egrep other
Allinterno di find -exec? (o simile)
Tieni presente che sto cercando una soluzione che potrei facilmente digitare quando ne ho bisogno. So che questo potrebbe essere fatto con poche righe usando uno script di shell, ma non è quello che sto cercando.
Risposta
Se devi farlo da find, devi chiamare una shell:
find ./ -type f -name "*.txt" -exec sh -c "grep -EiH something "$1" | grep -E somethingelse | grep -E other" sh {} \;
Altre alternative includono lutilizzo di xargs
:
find ./ -type f -name "*.txt" | xargs -I{} grep -EiH something {} | grep -EiH somethingelse | grep -EiH other
Oppure , molto più sicuro per nomi di file arbitrari (supponendo che find
supporti -print0
):
find ./ -type f -name "*.txt" -print0 | xargs -0 grep -EiH something {} | grep -Ei somethingelse | grep -Ei other
In alternativa, potresti semplicemente utilizzare un ciclo di shell:
find ./ -type f -name "*.txt" -print0 | while IFS= read -d "" file; do grep -Ei something "$file" | grep -Ei somethingelse | grep -Ei other done
Commenti
Risposta
Modifica: questa risposta non è preferita , ma viene lasciata qui per confronto e illustrazione di insidie potenzialmente pericolose nello scripting bash.
Puoi inserire bash
(o unaltra shell) come comando -exec
:
find -type -f -name "*.txt" -exec bash -c "egrep -iH something "{}" | egrep somethingelse | egrep other" \;
Uno degli svantaggi di farlo in questo modo è che crea più potenziale per problemi di quotazione annidata man mano che i comandi diventano più complessi. Se vuoi evitarlo, puoi suddividerlo in un for
-loop:
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
Commenti
- Il primo è esattamente quello che stavo cercando. Estremamente semplice e abbastanza piccolo da poter essere digitato a seconda delle mie esigenze. Grazie.
- Quel
for
loop è una pessima idea. Noto anche come bash trabocchetto # 1 . - Questo
"{}"
nel tuo primo comando può persino portare alliniezione di codice. Immagina di aver ricevuto file da me e ' è un file chiamato letteralmente" & rm -rf ~ & : ".txt
. Fortunatamente per te-type -f
non è valido, ha solo salvato la tua directory home. Correggi lerrore di battitura e riprova. 🙂 terdon ha fatto bene:find … -exec sh -c '… "$1" …' foo {} \;
. - Grazie per le informazioni! Sì,
-type -f
è un errore di battitura che faccio costantemente quando utilizzofind
e non ' non lo nota nella mia risposta. Ops. La risposta di terdon ' è migliore, ma ' la lascio a fini comparativi. - @terdon: tx per fare riferimento alla pagina mywiki.wooledge.org. ' è bello avere un gruppo di medici di famiglia riassunti in modo ordinato in un unico posto.
xargs
potrebbe anche essere usato comexargs -I {} sh -c '...' sh {}
, se si vuole (fa è possibile eseguire lavori paralleli con-P
se si desidera).