Jak uruchomić find -exec?

477

Chciałbym znaleźć pliki w bieżącym katalogu, które zawierają tekst „chrome”.

$ find . -exec grep chrome
find: missing argument to `-exec'

Co ja robię źle?

ripper234
źródło
Mamfind: Only one instance of {} is supported with -exec ... +
Costa
2
Powiązane: Jak korzystać -execzfind
Kusalananda

Odpowiedzi:

710

Przegapiłeś ;(uciekłeś tutaj, \;aby powłoka go nie interpretowała) lub a +i a {}:

find . -exec grep chrome {} \;

lub

find . -exec grep chrome {} +

findwykona się grepi zastąpi {}znalezione nazwy plików. Różnica między ;i +polega na tym, że dla każdego pliku wykonywana jest ;jedna grepkomenda, podczas gdy dla +jak największej liczby plików podano jednocześnie parametry grep.

bmk
źródło
30
Jeśli używasz \; końcowy konstrukt grep jest przekazywany jeden plik na raz, więc domyślnie nie wyświetla nazwy pliku, tylko dopasowane linie. Aby zamiast tego uzyskać listę plików, dodaj użycie grep -lswewnątrz konstrukcji find.
Caleb
9
find . -exec grep foo {} +pokaże ci takie wyniki./dir/file.py:from foo import bar
sg
10
find . -exec grep foo {} \;pokaże ci takie wynikifrom foo import bar
sg
9
find . -exec grep -l foo {} +pokaże ci takie wyniki./dir/file.py
sg
8
find . -exec grep -l foo {} \;pokaże ci taki wynik./dir/file.py
sg
46

W ogóle nie musisz tego używać find; grep jest w stanie obsłużyć otwieranie plików z globalnej listy wszystkiego w bieżącym katalogu:

grep chrome *

... lub nawet rekurencyjnie dla folderu i wszystkiego pod nim:

grep chrome . -R
Caleb
źródło
22
grep dusi się, jeśli rozszerzenie przekroczy ARG_MAX. -R odwiedzi wszystko podczas korzystania z funkcji znajdowania, można łatwiej dodawać prymitywy, aby wykluczyć niektóre pliki (-name itp.), A nawet nie odwiedzać poddrzewa (-prune).
Mel
6
Dobre punkty @Mel. Chodziło mi o to, że najprawdopodobniej strona pytająca sprawiła, że ​​sprawy były bardziej skomplikowane, niż trzeba, wprowadzając, findkiedy grepmożna wykonać zadanie, ale w niektórych przypadkach bardziej efektywne byłoby skorzystanie z funkcji znajdowania, aby dopracować listę plików przed wyjściem grep.
Caleb
4
@Mel grepw takim przypadku execnie dusi się .
Chris Down,
Działa tylko w przypadku, gdy wszystkie pliki znajdują się w tym samym katalogu, a nie gdy są one rozproszone w podkatalogach.
Yaba
1
@Yaba Moja odpowiedź mówi, jak obsługiwać przypadek plików rozproszonych w podkatalogach.
Caleb
18
find . | xargs grep 'chrome'

możesz także:

find . | xargs grep 'chrome' -ls

Pierwszy pokazuje linie w plikach, drugi po prostu wyświetla listę plików.

Opcja Caleba jest ładniejsza, mniej naciśnięć klawiszy.

Mathew
źródło
11
Problem xargspolega na tym, że oczekuje, że jego dane wejściowe będą cytowane w szczególny sposób, findktóry nie daje rezultatów. Więc find … | xargs …nie działa, jeśli masz nazwy plików zawierające białe znaki lub \'".
Gilles,
3
@Gilles Możesz obejść ten problem, używając czegoś takiego find . | xargs -n1 -iX grep "X" 'chrome', aby argumenty były podawane pojedynczo i cytowane. Oczywiście jest to strasznie nieefektywny sposób radzenia sobie z tym przykładem, ale w niektórych sytuacjach jest to przyjemne.
Caleb
Dla kompletności powinniśmy również wspomnieć o opcji -i dla niewrażliwości na wielkość liter w 'grep'. Istnieje również -iname w znajdowaniu dla niewrażliwości na wielkość liter.
Mathew
9
@Caleb: Jedynym w 100% niezawodnym sposobem xargsradzenia sobie z nazwami plików w Linuksie jest find ... -print0 | xargs -0użycie NUL jako separatora. Alternatywa - xargs -d '\n'zastosowanie separatora nowej linii, 99% niezawodności.
grawitacja
Używam tego często, ale nie powiedzie się to na bardzo długich listach nazw plików, w którym to momencie find -exec staje się zwycięzcą.
Spacemoose
5

Znajdź to jeden ze sposobów i możesz spróbować, the_silver_searchera następnie wystarczy

ag chrome

Przeszukuje chrome we wszystkich plikach (włączając podkatalogi) i jest szybszy niż znajdź

Zapytaj i naucz się
źródło
Istnieje również pt (wyszukiwarka platyny, dostępna na github.com/monochromegane/the_platinum_searcher ), która, IMHO, wykonuje zadanie szybciej - może nie mieć znaczenia, jeśli jest tylko kilka plików.
Hopping Bunny
1

Aby wyświetlić listę plików zamiast wierszy:

grep -l "chrome" *

lub:

grep -r -l "chrome" .
mateusz.szymborski
źródło
1

Oto przykład tego, jak zwykle używam find / exec ...

find  . -name "*.py" -print -exec fgrep hello {} \;

Wyszukuje rekurencyjnie wszystkie pliki .py, a dla każdego pliku drukuje nazwę pliku i fgrep dla 'witaj' w tym (dla każdego) pliku. Dane wyjściowe wyglądają (właśnie uruchomiłem dzisiaj):

./r1.py
./cgi-bin/tst1.py
print "hello"
./app/__init__.py
./app/views.py
./app/flask1.py
./run.py
./tst2.py
print "hello again"
jon
źródło
1
aby nie zadzierać z przepływem pracy, ale możesz chcieć: find . -name "*.py" -exec fgrep -l hello {} \; - wypisze nazwy plików pasujących plików i nic więcej
Jeff Schaller