Найти, выполнить и выполнить - все в одном? - PullRequest
17 голосов
/ 21 мая 2011

Это команда, которую я использовал для поиска совпадений (queryString) в файлах php, в текущем каталоге, с grep, без учета регистра и отображения результатов сопоставления в строке:

find . -iname "*php" -exec grep -iH queryString {} \;

Isесть ли способ также передать только имя файла совпадений другому сценарию?

Возможно, я мог бы выполнить команду -exec дважды, но это кажется неэффективным.

Что бы я хотелdo на Mac OS X на самом деле «показывает» этот файл в поисковике.Я думаю, что справлюсь с этой частью.Если бы мне пришлось отказаться от встроенных совпадений и просто позволить grep показать имена файлов, а затем передать это третьему скрипту, это тоже было бы хорошо - я бы согласился.

Но яНа самом деле я даже не уверен, как передать вывод (совпадающие имена файлов) куда-то еще ...

Помогите!:)

Уточнение

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

Я собираюсь запустить это в консоли, в идеале я хотел бы увидеть распечатки встроенных совпадений, а также возможность передать их в другой скрипт, например, oascript (applecript,выявить их в поисковике).Вот почему я использовал -H - потому что мне нравится видеть как имя файла, так и совпадение.

Если бы мне пришлось довольствоваться простым использованием -l, чтобы имя файла можно было легко передать по трубопроводук другому сценарию, это было бы тоже хорошо.Но я думаю, что, посмотрев ответ @Charlie Martin ниже, можно сказать, что xargs может быть полезен в этом случае одновременно с помощью одной команды find и одной команды grep.

Я сказал bash, но я не знаюна самом деле не против, если вместо этого нужно указать /bin/sh - я пока не слишком разбираюсь в различиях, но знаю, что есть некоторые важные.

Спасибо всем за ответы, я собираюсь попробовать некоторые из них в командной строке и посмотреть, смогу ли я заставить их работать, а затем думаю, что смогу выбрать лучший ответ.Оставьте комментарий, если хотите, чтобы я уточнил что-то еще.

Еще раз спасибо!

Ответы [ 9 ]

24 голосов
/ 21 мая 2011

Вы делаете ставку. Обычная вещь что-то вроде

  $ find /path -name pattern -print | xargs command

Так что вы можете, например, сделать

  $ find . -name '*.[ch]' -print | xargs grep -H 'main' 

(Тест: почему -H?)

Вы можете продолжать с этим дальше; например. вы можете использовать

  $ find . -name '*.[ch]' -print | xargs grep -H 'main' | cut -d ':' -f 1

, чтобы получить вектор имен файлов для файлов, которые содержат 'main', или

  $ find . -name '*.[ch]' -print | xargs grep -H 'main' | cut -d ':' -f 1 |
      xargs growlnotify -

чтобы каждое имя стало уведомлением Growl.

Вы могли бы также сделать

 $ grep pattern `find /path -name pattern`

или

 $ grep pattern $(find /path -name pattern)

bash (1) по крайней мере они эквивалентны), но вы можете ограничить длину командной строки таким образом.

Обновление

Чтобы ответить на ваши вопросы:

(1) Вы можете сделать что-нибудь в bash , что вы можете сделать в sh . Единственное, что я упомянул, это могло бы быть по-другому - использование $(command) вместо использования обратных галочек вокруг команды, и это работает в версии sh на Mac. Csh, zsh, ash и fish различны.

(2) Я думаю, что простое выполнение $ open $(dirname arg) откроет окно поиска в содержащей директории.

4 голосов
/ 21 мая 2011

Звучит так, как будто вы хотите открыть все *.php файлы, содержащие querystring, из сеанса Terminal.app.

Вы можете сделать это следующим образом:

find . -name '*.php' -exec grep -li 'querystring' {} \; | xargs open

С моей установкой, это открывает MacVim с каждым файлом на отдельной вкладке.YMMV.

4 голосов
/ 21 мая 2011

Замените -H на -l, и вы получите список тех имен файлов, которые соответствуют шаблону.

2 голосов
/ 22 мая 2011

если у вас есть bash4, просто выполните

grep pattern /path/**/*.php

оператор ** похож на

grep pattern `find -name \*.php -print`
2 голосов
/ 21 мая 2011
find /home/aaronmcdaid/Code/ -name '*.cpp' -exec grep -q -iH boost {} \; -exec echo {} \;

Первое, что я сделал, это добавил -q в вашу команду grep.Это «Выход немедленно с нулевым статусом, если найдено какое-либо совпадение».

Хорошая новость заключается в том, что это ускоряет grep, когда в файле много совпадающих строк.Тебе все равно, сколько там матчей.Но это означает, что нам нужен еще один exec в конце, чтобы фактически напечатать имена файлов, когда grep был успешным

1 голос
/ 21 мая 2011

Результат grep будет отправлен на стандартный вывод, так что другой предикат -exec, вероятно, является лучшим решением здесь.

1 голос
/ 21 мая 2011

Передача в другой сценарий:

 find . -iname "*.php" | myScript

Имена файлов будут появляться в строке myScript 1 одновременно.

Вы также можете использовать xargs дляформировать / выполнять команды для работы с каждым файлом:

 find . -iname "*.php" | xargs ls -l

действовать на файлы, которые вам соответствуют:

find . -iname "*.php" | xargs grep -l pattern | myScript

действовать, которые не соответствуют шаблону

find . -iname "*.php" | xargs grep -L pattern | myScript
0 голосов
/ 21 декабря 2017

Относительно вопроса о том, что быстрее, и вы на самом деле заботитесь о незначительной разнице во времени, которая может возникнуть, если вы попытаетесь увидеть, которая сэкономит ваш процессор некоторое время ... возможно, тестирование с использованием команды в качестве суффикса длякоманду «время», и посмотрите, какая из них работает лучше.

0 голосов
/ 24 октября 2014

Как правило, использование нескольких -exec и grep -q будет FAR быстрее, чем конвейерная, поскольку find подразумевает короткие замыкания -a, разделяющие каждую пару выражений, которые не разделены явным оператором. Основная проблема здесь в том, что вы хотите, чтобы что-то произошло, если grep соответствует чему-то И для совпадений, которые будут напечатаны. Если файлы имеют разумный размер, то это должно быть быстрее (потому что grep -q завершается после нахождения одного совпадения)

find . -iname "*php" -exec grep -iq queryString {} \; -exec grep -iH queryString {} \; -exec otherprogram {} \; 

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

find . -iname "*php" -exec bash -c \
  'out=$(grep -iH queryString "$1"); [[ -n $out ]] && echo "$out" && exit 0 || exit 1' \
bash {} \; -print 

Также обратите внимание, что если совпадения особо не нужны, то

find . -iname "*php" -exec grep -iq queryString {} \; -exec otherprogram {} \;

Практически всегда будет быстрее, чем такое решение, как

find . -iname "*php" -print0 | xargs -0 grep -iH | ...

Кроме того, у вас действительно должно быть -type f во всех случаях, если вы не хотите перехватывать *php каталогов

...