Найти, grep и выполнить - все в одном?

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

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

Есть ли способ передать только имя файла совпадений другому script?

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

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

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

Помощь!:)

Разъяснение

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

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

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

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

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

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

Ответы

Ответ 1

Вы ставите. Обычно это что-то вроде

  $ 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) вместо использования backticks вокруг команды, и это работает в версии sh на Mac. Csh, zsh, ash и fish отличаются.

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

Ответ 2

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

Ответ 3

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

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

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

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

Ответ 4

find /home/aaronmcdaid/Code/ -name '*.cpp' -exec grep -q -iH boost {} \; -exec echo {} \;

Первое изменение, которое я сделал, - добавить -q в команду grep. Это "Выход немедленно с нулевым статусом, если найдено совпадение".

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

Ответ 5

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

grep pattern /path/**/*.php

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

grep pattern `find -name \*.php -print`

Ответ 6

Труба в другую script:

 find . -iname "*.php" | myScript

Имена файлов войдут в stdin строки 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

Ответ 7

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

Ответ 8

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

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

Если файлы особенно велики, инкапсуляция в оболочку script может быть быстрее, чем выполнение нескольких команд 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 каталоги

Ответ 9

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