Załóżmy, że chcę znaleźć wszystkie pliki .txt i wyszukać jakiś ciąg. Zrobiłbym:

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

A jeśli chcę wykonać bardziej złożone filtrowanie, na przykład:

egrep something file.txt | egrep somethingelse | egrep other 

Inside find -exec? (lub podobny)

Proszę pamiętać, że szukam rozwiązania, które mógłbym łatwo wpisać, gdy go potrzebuję. Wiem, że można to zrobić za pomocą kilku wierszy przy użyciu skryptu powłoki, ale to nie jest to, czego szukam.

Odpowiedź

Jeśli musisz to zrobić z poziomu find, musisz wywołać powłokę:

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

Inne alternatywy obejmują użycie xargs zamiast tego:

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

Lub , znacznie bezpieczniejsze w przypadku dowolnych nazw plików (zakładając, że find obsługuje -print0):

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

Lub możesz zamiast tego po prostu użyć pętli powłoki:

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

Komentarze

  • Pierwsza jest dokładnie tym, czego szukałem. Niezwykle proste i wystarczająco małe, aby pisać w zależności od moich potrzeb. Dzięki.
  • … i xargs mogą być również użyte jako xargs -I {} sh -c '...' sh {}, gdyby ktoś chciał (sprawia, że możliwe jest uruchamianie równoległych zadań z -P, jeśli ktoś chciał).

Odpowiedź

Edytuj: ta odpowiedź jest nie jest preferowana , ale została tutaj dla porównania i zilustrowania potencjalnie niebezpiecznych pułapek w skryptach basha.


Możesz umieścić bash (lub inną powłokę) jako polecenie -exec:

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

Jedną z wad robienia tego w ten sposób jest to, że tworzy więcej potencjalne problemy z zagnieżdżonymi cytatami, gdy Twoje polecenia stają się bardziej złożone. Jeśli chcesz tego uniknąć, możesz podzielić to na 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  

Komentarze

  • Pierwsza jest dokładnie tym, czego szukałem. Niezwykle proste i wystarczająco małe, aby pisać w zależności od moich potrzeb. Dzięki.
  • Ta for pętla to bardzo zły pomysł. Znana również jako pułapka bash # 1 .
  • To "{}" w pierwszym poleceniu może nawet doprowadzić do wstrzyknięcia kodu. Wyobraź sobie, że masz pliki ode mnie i oto ' jest plik o dosłownej nazwie " & rm -rf ~ & : ".txt. Na szczęście -type -f jest nieprawidłowy, po prostu zapisał twój katalog domowy. Popraw literówkę i spróbuj ponownie. 🙂 terdon zrobił to dobrze: find … -exec sh -c '… "$1" …' foo {} \;.
  • Dzięki za informację! Tak, -type -f to literówka, którą ciągle popełniam, używając find, a nie ' nie zauważyłem tego w mojej odpowiedzi. Ups. terdon ' odpowiedź jest lepsza, ale ' zostawię to dla celów porównawczych.
  • @terdon: tx za odniesienie do strony mywiki.wooledge.org. ' Fajnie jest mieć kilka starannie podsumowanych lekarzy w jednym miejscu.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *