Это не работает Можно ли это сделать в find? Или мне нужно xargs?
find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;
Это не работает Можно ли это сделать в find? Или мне нужно 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» - это хороший способ отладки или выполнения пробных запусков командных строк, подобных этой.)
С точки зрения эффективности этот результат стоит одного вызова find, одного вызова sh, многочисленных вызовов zcat и многочисленных вызовов agrep.
Наиболее эффективным решением с точки зрения количества вызовов команд является предложение от Пола Томблина:
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
... который стоит один вызов find, один вызов xargs, несколько вызовов zcat и один вызов agrep.
-exec sh -c "… | … " \;
.
решение простое: выполнить через sh
... -exec sh -c "zcat {} | agrep -dEOE 'grep' " \;
-c
опцию. В противном случае вы получите удивительное No such file or directory
сообщение об ошибке.
find -type f -name '*.mdds' -exec sh -c "echo {} | sed -e 's/_[0-9]\+//g' | xargs mv {}" \;
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.M2009090-0800 .jar org / eclipse / core / привязка данных / наблюдаемый / список / 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 find выше; хотя findstr
это не делает сопоставляемую строку жирным шрифтом, поэтому вам нужно взглянуть немного ближе к выводу, чтобы увидеть соответствующее имя класса. Оказывается, команда windows 'for' знает немало хитростей, таких как циклический просмотр текстовых файлов ...
наслаждаться
Я обнаружил, что лучше всего работает команда string shell (sh -c), например:
find -name 'file_*' -follow -type f -exec bash -c "zcat \"{}\" | agrep -dEOE 'grep'" \;
Если вы ищете простую альтернативу, это можно сделать с помощью цикла:
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