Найти, 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
Что касается вопроса о том, что происходит быстрее, и вы действительно заботитесь о незначительной разнице во времени, которая, возможно, может возникнуть, если вы попытаетесь увидеть, какое время будет экономить ваш процессор... возможно, тестирование с использованием команды в качестве суффикса команда "время" и посмотрите, какой из них лучше работает.