Lad os antage, at jeg vil finde alle .txt
filer og søge efter en streng. Jeg ville gøre:
find ./ -type f -name "*.txt" -exec egrep -iH "something" "{}" \;
Hvad hvis jeg vil foretage en mere kompleks filtrering, som denne:
egrep something file.txt | egrep somethingelse | egrep other
Inside find -exec? (eller lignende)
Husk, at jeg leder efter en løsning, som jeg let kunne skrive, når jeg har brug for det. Jeg ved, at dette kunne gøres med et par linjer ved hjælp af et shell-script, men det er ikke det, jeg leder efter.
Svar
Hvis du skal gøre det inden for find, skal du ringe til en shell:
find ./ -type f -name "*.txt" -exec sh -c "grep -EiH something "$1" | grep -E somethingelse | grep -E other" sh {} \;
Andre alternativer inkluderer at bruge xargs
i stedet:
find ./ -type f -name "*.txt" | xargs -I{} grep -EiH something {} | grep -EiH somethingelse | grep -EiH other
Eller , meget sikrere for vilkårlige filnavne (forudsat at din find
understøtter -print0
):
find ./ -type f -name "*.txt" -print0 | xargs -0 grep -EiH something {} | grep -Ei somethingelse | grep -Ei other
Eller du kan bare bruge 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
Rediger: Dette svar er foretrækkes ikke , men er her til sammenligning og illustration af potentielt farlige faldgruber i bash scripting.
Du kan sætte bash
(eller en anden shell) som din -exec
kommando:
find -type -f -name "*.txt" -exec bash -c "egrep -iH something "{}" | egrep somethingelse | egrep other" \;
En af ulemperne ved at gøre det på denne måde er, at det skaber mere potentiale for nestede citatproblemer, da dine kommandoer bliver mere komplekse. Hvis du vil undgå det, kan du bryde det ud 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 nøjagtigt hvad jeg ledte efter. Ekstremt enkel og lille nok til at skrive afhængigt af mine behov. Tak.
- At
for
loop er en meget dårlig idé. Også kendt som bash faldgrube # 1 . - Denne
"{}"
i din første kommando kan endda føre til kodeinjektion. Forestil dig, at du har filer fra mig, og der er ' en fil, der bogstaveligt talt hedder" & rm -rf ~ & : ".txt
. Heldigvis for dig er-type -f
ugyldig, det har bare gemt din hjemmekatalog. Ret skrivefejl og prøv igen. 🙂 terdon gjorde det rigtigt:find … -exec sh -c '… "$1" …' foo {} \;
. - Tak for informationen! Ja,
-type -f
er en tastefejl, jeg konstant laver, når jeg brugerfind
, og jeg gjorde ikke ' t bemærker det i mit svar. Ups. terdon ' s svar er bedre, men jeg ' lader dette være til sammenligningsformål. - @terdon: tx for at henvise til mywiki.wooledge.org siden. Det er ' dejligt at have en flok læger samlet på et sted.
xargs
kunne også bruges somxargs -I {} sh -c '...' sh {}
, hvis man ville (det gør det er muligt at køre parallelle job med-P
hvis man vil).