Låt oss anta att jag vill hitta alla .txt filer och söka efter någon sträng. Jag skulle göra:

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

Vad händer om jag vill göra en mer komplex filtrering, så här:

egrep something file.txt | egrep somethingelse | egrep other 

Inside find -exec? (eller liknande)

Tänk på att jag letar efter en lösning som jag lätt skulle kunna skriva när jag behöver den. Jag vet att detta kan göras med några rader med ett skalskript, men det är inte det jag letar efter.

Svar

Om du måste göra det inifrån söka måste du ringa ett skal:

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

Andra alternativ inkluderar att använda xargs istället:

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

Eller , mycket säkrare för godtyckliga filnamn (förutsatt att din find stöder -print0):

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

Eller du kan bara använda en skalslinga istället:

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örsta är precis vad jag letade efter. Extremt enkel och tillräckligt liten för att skriva beroende på mina behov. Tack.
  • … och xargs kan också användas som xargs -I {} sh -c '...' sh {}, om man vill (det gör det är möjligt att köra parallella jobb med -P om man vill).

Svar

Edit: Detta svar är inte föredraget , men lämnas här för jämförelse och illustration av potentiellt farliga fallgropar i bash-skript.


Du kan sätta bash (eller ett annat skal) som ditt -exec -kommando:

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

En av nackdelarna med att göra det på det här sättet är att det skapar mer potential för kapslade citatfrågor när dina kommandon blir mer komplexa. Om du vill undvika det kan du dela upp det 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örsta är precis vad jag letade efter. Extremt enkel och tillräckligt liten för att skriva beroende på mina behov. Tack.
  • Att for loop är en mycket dålig idé. Även känd som bash fallgrop nr 1 .
  • Detta "{}" i ditt första kommando kan till och med leda till kodinjektion. Tänk dig att du har filer från mig och att ' är en fil som bokstavligen heter " & rm -rf ~ & : ".txt. Lyckligtvis för dig -type -f är ogiltigt, det sparade bara din hemkatalog. Åtgärda skrivfelet och försök igen. 🙂 terdon gjorde det rätt: find … -exec sh -c '… "$1" …' foo {} \;.
  • Tack för informationen! Ja, -type -f är ett stavfel som jag gör ständigt när jag använder find, och jag gjorde inte ' t märker det i mitt svar. Oj då. terdon ' svaret är bättre, men jag ' lämnar detta för jämförande ändamål.
  • @terdon: tx för att hänvisa till mywiki.wooledge.org-sidan. Det ' är trevligt att ha en massa allmänläkare som sammanfattas snyggt på ett ställe.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *