Как запустить find -exec?


478

Я хотел бы найти файлы в текущем каталоге, которые содержат текст «хром».

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

Что я делаю неправильно?



Я получилfind: Only one instance of {} is supported with -exec ... +
Коста

Ответы:


712

Вы пропустили ;(избежали, \;чтобы не интерпретировать его оболочкой) или a +и a {}:

find . -exec grep chrome {} \;

или же

find . -exec grep chrome {} +

findвыполнится grepи заменит {}найденные имена файлов. Разница между ;и +заключается в том, что с ;помощью одной grepкоманды для каждого файла выполняется, в то время +как для максимально возможного числа файлов в качестве параметров указывается grepодновременно.


30
Если вы используете \; Конечная конструкция grep передается по одному файлу за раз, поэтому по умолчанию имя файла не отображается, только совпадающие строки. Чтобы получить список файлов, вместо этого добавьте use grep -lsвнутри конструкции find.
Калеб

9
find . -exec grep foo {} +покажет вам такой вывод./dir/file.py:from foo import bar
sg

10
find . -exec grep foo {} \;покажет вам вывод, как этоfrom foo import bar
sg

9
find . -exec grep -l foo {} +покажет вам вывод, как это./dir/file.py
sg

8
find . -exec grep -l foo {} \;покажет вам такой вывод./dir/file.py
sg

46

Вам не нужно использовать findдля этого вообще; grep может справиться с открытием файлов из списка глобальных файлов в текущем каталоге:

grep chrome *

... или даже рекурсивно для папки и всего, что находится под ней:

grep chrome . -R

22
grep захлебнется, если расширение переходит ARG_MAX. -R будет посещать все, а используя find, можно легко добавлять примитивы для исключения определенных файлов (-name и т. Д.) Или даже не посещать поддеревья (-prune).
Мел

6
Хорошие очки @Mel. Моя точка зрения заключалась в том, что, по всей вероятности, запрашивающая сторона делала вещи более сложными, чем нужно, представляя, findкогда grepможно выполнить работу, но в некоторых случаях было бы более эффективно использовать find для точного отображения списка файлов перед выходом на улицу. grep.
Калеб

4
@Mel grepне душит в таком случае, execделает.
Крис Даун

Работает только в том случае, если все файлы находятся в одном и том же каталоге, а не когда они распределены по подкаталогам.
Яба

1
@Yaba В моем ответе указано, как обрабатывать файлы, распределенные по подкаталогам.
Калеб

18
find . | xargs grep 'chrome'

Вы также можете сделать:

find . | xargs grep 'chrome' -ls

Первый показывает вам строки в файлах, второй просто перечисляет файлы.

Вариант Калеба аккуратнее, меньше нажатий клавиш.


11
Проблема в xargsтом, что он ожидает, что его входные данные будут процитированы особым образом, findкоторый не производит. Так find … | xargs …что не работает, если у вас есть имена файлов, содержащие пробелы или \'".
Жиль

3
@ Жиль Вы можете обойти эту проблему, используя что-то вроде find . | xargs -n1 -iX grep "X" 'chrome'того, чтобы аргументы передавались по одному и приводились в кавычки. Очевидно, это ужасно неэффективный способ справиться с этим примером, но в некоторых ситуациях это приятно.
Калеб

Для полноты мы также должны упомянуть опцию -i для нечувствительности к регистру с помощью 'grep'. Также есть -iname в find для нечувствительности к регистру.
Мэтью

9
@Caleb: единственный надежный способ xargsсправиться с именами файлов в Linux - это find ... -print0 | xargs -0использовать NUL в качестве разделителя. Альтернатива - xargs -d '\n'использование новой строки в качестве разделителя, надежность 99%.
grawity

Я использую это часто, но это не удастся для очень длинных списков имен файлов, после чего find -exec становится победителем.
Космический лось

5

Найти это один из способов, и вы можете попробовать the_silver_searcherвсе, что вам нужно сделать, это

ag chrome

Он будет искать Chrome во всех файлах (включая подкаталоги), и это быстрее, чем найти


Существует также pt (платиновый поисковик, доступный по адресу github.com/monochromegane/the_platinum_searcher ), который, IMHO, делает работу быстрее - может не иметь значения, если файлов всего несколько.
Прыгающий кролик


1

Вот пример того, как я обычно использую find / exec ...

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

При этом выполняется рекурсивный поиск всех файлов .py, и для каждого файла выводятся имя файла и fgrep для «привет» в этом (для каждого) файла. Вывод выглядит так (только что запустил сегодня):

./r1.py
./cgi-bin/tst1.py
print "hello"
./app/__init__.py
./app/views.py
./app/flask1.py
./run.py
./tst2.py
print "hello again"

1
не связываться с вашим рабочим процессом, но вам может понравиться: find . -name "*.py" -exec fgrep -l hello {} \; - он напечатает имена файлов, которые совпадают, и ничего больше
Джефф Шаллер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.