La oss anta at jeg vil finne alle .txt filer og søke etter en streng. Jeg ville gjort:

find ./ -type f -name "*.txt" -exec egrep -iH "something" "{}" \; 

Hva om jeg vil gjøre en mer kompleks filtrering, slik:

egrep something file.txt | egrep somethingelse | egrep other 

Inside find -exec? (eller lignende)

Husk at jeg søker etter en løsning som jeg enkelt kan skrive når jeg trenger det. Jeg vet at dette kan gjøres med noen få linjer ved hjelp av et skallskript, men det er ikke det jeg leter etter.

Svar

Hvis du må gjøre det innenfra finn, må du ringe et skall:

find ./ -type f -name "*.txt" -exec sh -c "grep -EiH something "$1" | grep -E somethingelse | grep -E other" sh {} \; 

Andre alternativer inkluderer å bruke xargs i stedet:

find ./ -type f -name "*.txt" | xargs -I{} grep -EiH something {} | grep -EiH somethingelse | grep -EiH other 

Eller , mye tryggere for vilkårlige filnavn (forutsatt at find støtter -print0):

find ./ -type f -name "*.txt" -print0 | xargs -0 grep -EiH something {} | grep -Ei somethingelse | grep -Ei other 

Eller du kan bare bruke en shell loop i stedet:

find ./ -type f -name "*.txt" -print0 | while IFS= read -d "" file; do grep -Ei something "$file" | grep -Ei somethingelse | grep -Ei other done 

Kommentarer

  • Den første er akkurat det jeg lette etter. Ekstremt enkel og liten nok til å skrive, avhengig av mine behov. Takk.
  • … og xargs kan også brukes som xargs -I {} sh -c '...' sh {}, hvis man ville (det gjør det er mulig å kjøre parallelle jobber med -P hvis man vil).

Svar

Edit: Dette svaret er ikke foretrukket , men er igjen her for sammenligning og illustrasjon av potensielt farlige fallgruver i bash-skript.


Du kan sette bash (eller et annet skall) som -exec -kommandoen:

 find -type -f -name "*.txt" -exec bash -c "egrep -iH something "{}" | egrep somethingelse | egrep other" \;  

En av ulempene ved å gjøre det på denne måten er at det skaper mer potensial for nestede siteringsproblemer etter hvert som kommandoene dine blir mer komplekse. Hvis du vil unngå det, kan du dele det opp i en 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  

Kommentarer

  • Den første er akkurat det jeg lette etter. Ekstremt enkel og liten nok til å skrive, avhengig av mine behov. Takk.
  • At for loop er en veldig dårlig idé. Også kjent som bash fallgruve # 1 .
  • Denne "{}" i din første kommando kan til og med føre til kodeinjeksjon. Tenk deg at du har filer fra meg, og der er ' en fil som bokstavelig talt heter " & rm -rf ~ & : ".txt. Heldigvis for deg -type -f er ugyldig, det lagret bare hjemmekatalogen din. Løs skrivefeil og prøv igjen. 🙂 terdon gjorde det riktig: find … -exec sh -c '… "$1" …' foo {} \;.
  • Takk for informasjonen! Ja, -type -f er en skrivefeil jeg lager hele tiden når jeg bruker find, og jeg gjorde ikke ' ikke merker det i svaret mitt. Uss. terdon ' s svar er bedre, men jeg ' la dette være for sammenlignende formål.
  • @terdon: tx for å referere til mywiki.wooledge.org-siden. Det ' er hyggelig å ha en haug med allmennleger pent oppsummert på ett sted.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *