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
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ącfind
, 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.
xargs
mogą być również użyte jakoxargs -I {} sh -c '...' sh {}
, gdyby ktoś chciał (sprawia, że możliwe jest uruchamianie równoległych zadań z-P
, jeśli ktoś chciał).