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
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 brukerfind
, 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.
xargs
kan også brukes somxargs -I {} sh -c '...' sh {}
, hvis man ville (det gjør det er mulig å kjøre parallelle jobber med-P
hvis man vil).