Как я могу получить результаты FIND, используя -EXEC, и при этом вывести их в файл?

64

Лучше объяснить на примерах.

Я могу:

find . -name "*.py" -type f > output.txt

Но как я могу сохранить вывод в том же файле для:

find . -name "*.py" -type f -exec grep "something" {} \

Я не могу просто сделать

find . -name "*.py" -type f -exec grep "something" {} \ > output.txt
bakytn
источник

Ответы:

106

Если я вас правильно понимаю, это то, что вы хотите сделать:

find . -name '*.py' -print0 | xargs -0 grep 'something' > output.txt

Findвсе файлы с расширением py, grepтолько строки, содержащие somethingи сохраняющие строки в output.txt. Если файл содержит что-либо, он будет заменен.

Редактировать: Используя -exec:

find . -name '*.py' -exec grep 'something' {} \; > output.txt

Я включил комментарий Криса Даунса здесь. Приведенная выше команда будет grepвыполняться столько раз, сколько будет findнайдено. Тем не менее, если вы замените ;с +, grepвызываются с выходом из findконкатенации (до определенного предела). Смотрите вопрос Использование точки с запятой (;) против плюс (+) с exec в find для получения дополнительной информации по этому вопросу.

Джонни
источник
16
Используйте +вместо \;, это значительно улучшит время выполнения (поскольку оно будет содержать аргументы до выполнения и до ARG_MAX).
Крис Даун
Теперь я понимаю силу xargs! Спасибо!
Домих
5
Используйте, grep -Hесли вы хотите включить имя файла в вывод.
Стейнар
18

Если вы хотите сохранить все совпадающие строки во всех файлах output.txt, ваша последняя команда работает, за исключением того, что вы пропустили обязательное ;в конце команды.

find . -name "*.py" -type f -exec grep "something" {} \; > output.txt

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

find . -name "*.py" -type f -exec sh -c 'grep "something" <"$0" >"$0.txt"' {} \;
Жиль "ТАК - перестань быть злым"
источник
последний действительно хороший: D
Bakytn
Чтобы развернуть ответ @gilles, сделав его немного более информативным, особенно если список файлов, с которыми вы имеете дело, велик, вы можете сообщить имя файла (относительный путь) каждого файла вместе с результатами grep, используя это : find . -name "*.py" -type f -exec grep "something" {} \; -print > output.txt И если вы хотите увидеть номера строк grep'-строк, вы можете, конечно, использоватьgrep -n "something"
JJMpls
9

Для записи, grepимеет --includeи --excludeаргументы, которые вы можете использовать для фильтрации файлов, которые она ищет:

grep -r --include="*.py" "something" > output.txt
hunse
источник
2
По крайней мере, GNU grepделает.
Phk
2

Используйте tee:

find . -name '*.py' | tee output.txt | xargs grep 'something'

Протест, если у вас есть какие - либо файлы с помощью специальных символов (включая пробелы) , что xargsи grepне будет хорошо работать ( a file.txtбудет интерпретироваться как два файла, aа file.txt). Альтернативой этому является использование либо, -xлибо -print0, но любой из них будет загрязнять ваш output.txt. -xБудет использовать , \чтобы избежать некоторых специальных символов , и это будет output.txt. В -print0качестве разделителя полей будет использоваться нулевой байт (который также требуется xargs -0) и output.txtбудет выглядеть как одна длинная непрерывная строка текста.

Как вы справляетесь (или не имеете) с этим, зависит только от вас.

bahamat
источник