Stel dat ik alle .txt
bestanden wil vinden en naar een string wil zoeken. Ik zou doen:
find ./ -type f -name "*.txt" -exec egrep -iH "something" "{}" \;
Wat moet ik doen als ik een complexere filtering wil doen, zoals deze:
egrep something file.txt | egrep somethingelse | egrep other
Inside find -exec? (of vergelijkbaar)
Houd er rekening mee dat ik op zoek ben naar een oplossing die ik gemakkelijk kan typen als ik die nodig heb. Ik weet dat dit kan worden gedaan met een paar regels met behulp van een shell-script, maar dat is niet wat ik zoek.
Answer
Als je het vanuit find moet doen, moet je een shell aanroepen:
find ./ -type f -name "*.txt" -exec sh -c "grep -EiH something "$1" | grep -E somethingelse | grep -E other" sh {} \;
Andere alternatieven zijn onder meer het gebruik van xargs
in plaats daarvan:
find ./ -type f -name "*.txt" | xargs -I{} grep -EiH something {} | grep -EiH somethingelse | grep -EiH other
Of , veel veiliger voor willekeurige bestandsnamen (ervan uitgaande dat uw find
-print0
ondersteunt):
find ./ -type f -name "*.txt" -print0 | xargs -0 grep -EiH something {} | grep -Ei somethingelse | grep -Ei other
Of je zou in plaats daarvan gewoon een shell-loop kunnen gebruiken:
find ./ -type f -name "*.txt" -print0 | while IFS= read -d "" file; do grep -Ei something "$file" | grep -Ei somethingelse | grep -Ei other done
Reacties
Antwoord
Bewerken: dit antwoord is niet de voorkeur , maar wordt hier gelaten ter vergelijking en illustratie van potentieel gevaarlijke valkuilen in bash scripting.
Je kunt bash
(of een andere shell) plaatsen als je -exec
commando:
find -type -f -name "*.txt" -exec bash -c "egrep -iH something "{}" | egrep somethingelse | egrep other" \;
Een van de nadelen van het op deze manier doen is dat er meer potentieel voor geneste aanhalingsproblemen naarmate uw opdrachten complexer worden. Als je dat wilt vermijden, kun je het opsplitsen in een 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
Reacties
- De eerste is precies wat ik zocht. Uiterst eenvoudig en klein genoeg om te typen, afhankelijk van mijn behoeften. Bedankt.
- Die
for
lus is een heel slecht idee. Ook bekend als valkuil # 1 . - Dit
"{}"
in uw eerste commando kan zelfs leiden tot code-injectie. Stel je voor dat je bestanden van mij hebt en er ' een bestand is dat letterlijk" & rm -rf ~ & : ".txt
heet. Gelukkig voor jou is-type -f
ongeldig, het heeft zojuist je homedirectory opgeslagen. Los de typfout op en probeer het opnieuw. 🙂 terdon deed het goed:find … -exec sh -c '… "$1" …' foo {} \;
. - Bedankt voor de informatie! Ja, de
-type -f
is een typefout die ik constant maak bij het gebruik vanfind
, en dat deed ik niet ' merk het niet in mijn antwoord. Oeps. terdon ' s antwoord is beter, maar ik ' laat dit achter voor vergelijkingsdoeleinden. - @terdon: tx voor het verwijzen naar de mywiki.wooledge.org-pagina. Het ' is fijn om een aantal huisartsen netjes op één plek samen te vatten.
xargs
kunnen ook worden gebruikt alsxargs -I {} sh -c '...' sh {}
, als je dat wilt (het maakt het is mogelijk om parallelle taken uit te voeren met-P
als men dat zou willen).