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

  • De eerste is precies wat ik zocht. Uiterst eenvoudig en klein genoeg om te typen, afhankelijk van mijn behoeften. Bedankt.
  • … en xargs kunnen ook worden gebruikt als xargs -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).

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 van find, 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.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *