Как включить трубку | в моем Linux найти команду -exec?

Это не работает. Можно ли это сделать в поиске? Или мне нужны xargs?

find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;

Ответ 1

Задача интерпретации символа трубы как инструкции для запуска нескольких процессов и передачи вывода одного процесса во вход другого процесса лежит на оболочке (/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.

Ответ 2

решение легко: выполнить через sh

... -exec sh -c "zcat {} | agrep -dEOE 'grep' " \;

Ответ 3

find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'

Ответ 4

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

пользоваться

Ответ 5

Если вы ищете простую альтернативу, это можно сделать с помощью цикла:

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