Это не работает. Можно ли это сделать в поиске? Или мне нужны xargs?
find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;
Это не работает. Можно ли это сделать в поиске? Или мне нужны xargs?
find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;
Задача интерпретации символа трубы как инструкции для запуска нескольких процессов и передачи вывода одного процесса во вход другого процесса лежит на оболочке (/bin/sh или эквивалентной).
В вашем примере вы можете либо использовать свою оболочку верхнего уровня для выполнения таких строк:
find -name 'file_*' -follow -type f -exec zcat {} \; | agrep -dEOE 'grep'
В терминах эффективности эти результаты обходятся одним вызовом find, многочисленными вызовами zcat и одним вызовом agrep.
Это приведет к тому, что будет создан только один процесс agrep, который будет обрабатывать весь вывод, созданный многочисленными вызовами zcat.
Если вы по какой-то причине хотите несколько раз вызывать agrep, вы можете сделать:
find . -name 'file_*' -follow -type f \
-printf "zcat %p | agrep -dEOE 'grep'\n" | sh
Это создает список команд, использующих трубы для выполнения, а затем отправляет их в новую оболочку для фактического выполнения. (Опустить окончательный "| sh" - отличный способ отладки или выполнения сухих прогонов командной строки, подобных этому.)
В терминах эффективности эти результаты обходятся одним вызовом поиска, одним вызовом sh, многочисленными вызовами zcat и многочисленными вызовами agrep.
Наиболее эффективным решением с точки зрения количества командных вызовов является предложение Пауля Томблина:
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
... который стоит один вызов find, один вызов xargs, несколько invocations zcat и один вызов agrep.
решение легко: выполнить через sh
... -exec sh -c "zcat {} | agrep -dEOE 'grep' " \;
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
Вы также можете подключиться к циклу while
, который может выполнять несколько действий над файлом, который находит find
. Итак, вот один для поиска в архивах jar
для данного файла класса java в папке с большим дистрибутивом jar
файлов
find /usr/lib/eclipse/plugins -type f -name \*.jar | while read jar; do echo $jar; jar tf $jar | fgrep IObservableList ; done
ключевым моментом является то, что цикл while
содержит несколько команд, ссылающихся на переданное в имени файла, разделенных точкой с запятой, и эти команды могут включать в себя каналы. Поэтому в этом примере я повторяю имя соответствующего файла, а затем перечисляю то, что находится в фильтрации архива для данного имени класса. Результат выглядит так:
/usr/lib/eclipse/plugins/org.eclipse.core.contenttype.source_3.4.1.R35x_v20090826-0451.jar /usr/lib/eclipse/plugins/org.eclipse.core.databinding.observable_1.2.0.M20090902-0800.jar орг/затмение/ядро /привязки/наблюдаемыми/список/ IObservableList.class /usr/lib/eclipse/plugins/org.eclipse.search.source_3.5.1.r351_v20090708-0800.jar /usr/lib/eclipse/plugins/org.eclipse.jdt.apt.core.source_3.3.202.R35x_v20091130-2300.jar /usr/lib/eclipse/plugins/org.eclipse.cvs .source_1.0.400.v201002111343.jar /usr/lib/eclipse/plugins/org.eclipse.help.appserver_3.1.400.v20090429_1800.jar
в моей оболочке bash (xubuntu10.04/xfce) он действительно делает совпадающее имя класса жирным, так как fgrep
выделяет совпадающую строку; это позволяет легко просканировать список сотен файлов jar
, которые были найдены, и легко увидеть любые совпадения.
на окнах вы можете сделать то же самое:
for /R %j in (*.jar) do @echo %j & @jar tf %j | findstr IObservableList
обратите внимание, что в этом случае в окнах разделитель команд равен '&' не ';' и что "@" подавляет эхо команды, чтобы дать аккуратный вывод, как и вывод вывода linux выше; хотя findstr
не делает выделенную строку полужирным, поэтому вам нужно немного приблизиться к выходу, чтобы увидеть совпадающее имя класса. Оказывается, что команда windows for for знает немало трюков, таких как цикл через текстовые файлы...
пользоваться
Если вы ищете простую альтернативу, это можно сделать с помощью цикла:
for i in $(find -name 'file_*' -follow -type f);do zcat $i | agrep -dEOE 'grep');done
или, более общая и простая для понимания форма:
for i in $(YOUR_FIND_COMMAND);do YOUR_EXEC_COMMAND_AND_PIPES );done
и замените {} на $ i в YOUR_EXEC_COMMAND_AND_PIPES