Это не работает. Можно ли это сделать в поиске? Или мне нужно xargs?
find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;





find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
Это не работает с файлами, в именах которых есть пробелы; чтобы исправить, замените -print на -print0 и добавьте параметр -0 в xargs
@someguy - Что? Избегаете xargs из соображений эффективности? Вызов одного экземпляра zcat и передача ему списка из нескольких файлов далеко более эффективен, чем выполнение его нового экземпляра для каждого найденного файла.
@ Адам - Я внес предложенные вами изменения. В 99% случаев, когда я делаю находки, они находятся в моих каталогах с исходным кодом, и ни в одном из файлов там нет пробелов, поэтому я не беспокоюсь о print0. С другой стороны, теперь в моем каталоге документов я помню файл print0.
решение простое: выполнить через sh
... -exec sh -c "zcat {} | agrep -dEOE 'grep' " \;
То, что OP пытался выполнить, можно встретить с помощью приведенных выше предложений, но это тот, который на самом деле отвечает на заданный вопрос. Для этого есть причины - exec намного мощнее, чем просто работа с файлами, возвращаемыми с помощью find, особенно в сочетании с test. Например: найдите geda-gaf / -type d -exec bash -c 'DIR = {}; [[$ (найти $ DIR -maxdepth 1 | xargs grep -i spice | wc -l) -ge 5]] && echo $ DIR '\; Вернет все каталоги в пути поиска, которые содержат в общей сложности более 5 строк среди всех файлов в этом каталоге, содержащих слово spice
Лучший ответ. Grepping всего вывода (как предполагают другие ответы) - это не то же самое, что grep each file. Совет: вместо sh вы можете использовать любую другую оболочку, какую захотите (я пробовал это с помощью bash, и она работает нормально).
Не упускайте из виду вариант -c. В противном случае вы получите сбивающее с толку сообщение об ошибке No such file or directory.
вот отличная замена ps, которая использует find с конвейером внутри оболочки exec'd: / usr / bin / find / proc -mindepth 1 -maxdepth 1 -type d -regex '. * / [0-9] +' - print -exec bash -c "cat {} / cmdline | tr '\\ 0' ''; echo" \;
Пример поиска файлов и их переименования в sed с использованием регулярного выражения find -type f -name '*.mdds' -exec sh -c "echo {} | sed -e 's/_[0-9]\+//g' | xargs mv {}" \;
Задача интерпретации символа вертикальной черты как инструкции для запуска нескольких процессов и перенаправления вывода одного процесса на вход другого процесса является обязанностью оболочки (/ bin / sh или эквивалентной).
В вашем примере вы можете выбрать использование оболочки верхнего уровня для выполнения трубопровода следующим образом:
find -name 'file_*' -follow -type f -exec zcat {} \; | agrep -dEOE 'grep'
С точки зрения эффективности, это требует одного вызова find, нескольких вызовов zcat и одного вызова согласования.
Это приведет к тому, что будет порожден только один процесс согласования, который будет обрабатывать весь вывод, произведенный многочисленными вызовами zcat.
Если по какой-то причине вы хотите запускать соглашение несколько раз, вы можете:
find . -name 'file_*' -follow -type f \
-printf "zcat %p | agrep -dEOE 'grep'\n" | sh
Это создает список команд с использованием каналов для выполнения, а затем отправляет их в новую оболочку для фактического выполнения. (Отсутствие последнего символа "| sh" - хороший способ отладить или выполнить пробный запуск командных строк, подобных этой.)
С точки зрения эффективности, этот результат стоит одного вызова find, одного вызова sh, многочисленных вызовов zcat и многочисленных вызовов согласования.
Наиболее эффективное решение с точки зрения количества вызовов команд - это предложение Пола Томблина:
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
... что стоит одного вызова find, одного вызова xargs, нескольких вызовов zcat и одного вызова согласования.
Еще одним преимуществом xargs является то, что вы можете еще больше ускорить его с помощью современных многоядерных процессоров, используя переключатель -P (-P 0).
Да, ключ -P действительно хороший способ ускорить выполнение в целом. К сожалению, вы рискуете, что выходные данные параллельных процессов zcat будут переданы по конвейеру с чередованием согласования, что повлияет на результат. Этот эффект можно продемонстрировать с помощью: echo -e "1 \ n2" | xargs -P 0 -n 1 да | уникальный
@ Адам, я внес предложенные вами изменения.
для которой вы можете установить великолепную команду xjobs (изначально из Solaris)
Что за зверь, printf с sh. Ты жжешь.
Более простой и общий ответ на stackoverflow.com/a/21825690/42973: -exec sh -c "… | … " \;.
Вы также можете подключиться к циклу 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 org / eclipse / core / databinding / наблюдаемый / список / 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
обратите внимание, что в Windows разделителем команд является '&' not; ' и что '@' подавляет эхо команды, чтобы получить аккуратный вывод, как и результат поиска linux выше; хотя findstr не выделяет совпадающую строку жирным шрифтом, поэтому вам нужно немного внимательнее присмотреться к выходным данным, чтобы увидеть имя совпадающего класса. Оказывается, команда Windows 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
Я обнаружил, что лучше всего работает строковая команда оболочки (sh -c), например:
find -name 'file_*' -follow -type f -exec bash -c "zcat \"{}\" | agrep -dEOE 'grep'" \;
Надеемся избежать -print и xargs по соображениям эффективности. Может быть, это действительно моя проблема: find не может обрабатывать команды через конвейер через -exec