2009-05-14 7 views
159

Я делаю find, а затем получаю список файлов. Как я могу подключить его к другой утилите, например cat (так что кошка отображает содержимое всех этих файлов) и в основном нужно grep что-то из этих файлов.Как передать список файлов, возвращаемых командой find, чтобы просмотреть все файлы

ответ

264
  1. трубопровода к другому процессу (хотя это не будет выполнять то, что вы сказали, что вы пытаетесь сделать):

    command1 | command2 
    

    Это направит выход command1 как вход команды команда2

  2. -exec на find (это будет делать то, что вы хотели сделать - но только для find)

    find . -name '*.foo' -exec cat {} \; 
    

    (Все между find и -exec - это предикаты поиска, которые вы уже использовали. {} заменит конкретный файл, который вы нашли в команде (cat {} в этом случае); \; является для завершения команды -exec)

  3. отправить выход одного процесса в качестве аргументов командной строки к другому процессу

    command2 `command1` 
    

    , например:.

    cat `find . -name '*.foo' -print` 
    

    (Примечание эти обратно- QUOTES не регулярные кавычки (под тильдой ~ на моей клавиатуре).) Это приведет к выходу command1 в command2 в качестве аргументов командной строки. Обратите внимание, что имена файлов, содержащие пробелы (новые строки и т. Д.), Будут разбиты на отдельные аргументы.

+2

cat 'find -name '* .foo' -print' отлично подойдет для меня ... Спасибо –

+0

Backquotes отлично работают и более обобщен, вы можете использовать это, чтобы cat список файлов из файла. – Hazok

+11

Обратите внимание, что современные версии 'find' позволяют вам писать:' find. -name '* .foo' -exec cat {} + ', где' + 'указывает, что' find' должен группировать как можно больше имен файлов в один командный вызов. Это очень полезно (он имеет дело с пробелами и т. Д. В именах файлов, не прибегая к '-print0' и' xargs -0'). –

6

Похоже, работа для сценария оболочки для меня:

for file in 'find -name *.xml' 
do 
    grep 'hello' file 
done 

или что-то подобное

+2

Это действительный, хотя и не обязательно оптимальный ответ на вопрос. –

+1

... да, но это здорово, если вам нужен один большой файл с именами, перечисленными также. –

+1

Мне нравится это лучшее. Такой блок петли оставляет место, чтобы делать другие вещи. – kakyo

62
find . -print | xargs grep something 

Если вы находитесь на Linux или имеют GNU find и xargs, а затем использовать -print0 с find и -0 с xargs для обработки имен файлов, содержащих пробелы и другие символы нечетного шара.

Если вы не хотите, чтобы имена файлов - только текст - добавьте соответствующую опцию в grep (обычно -h для подавления «заголовков»). Чтобы абсолютно гарантировать, что имя файла напечатано grep (даже если найден только один файл или последнему вызову grep присваивается только одно имя файла), затем добавьте /dev/null в командную строку xargs, чтобы всегда было по крайней мере два имени файла.


Обратите внимание, что POSIX 2008 добавило + маркера find, который означает, что он теперь автоматически группы, как много файлов, которые являются разумными в одном исполнение команды, очень похож xargs делает, но с целым рядом преимуществ:

  1. Вам не нужно беспокоиться о нечетных символах в именах файлов.
  2. Вам не нужно беспокоиться о вызове команды с нулевыми именами файлов.

Оба эти вопроса являются с xargs без опции -0. Таким образом, вы могли бы толково написать:

find . -exec grep something {} + 
+0

Для тех, кто смущен, как и я, обратите внимание, что этот путь сначала даст весь вывод find, а затем даст результат 'xargs grep something'. –

+2

@EricHu: Я вижу, что вы в замешательстве, но он не делает то, что вы говорите, по крайней мере, не на какой-либо системе на основе Unix, о которой я знаю. Выход 'find' отправляется на стандартный вход' xargs'. Программа «xargs» считывает свой стандартный ввод, разделяя входные данные на пробел (пробелы, символы новой строки, вкладки и т. Д.) И добавляет несколько слов в команду 'grep something' и выполняет командную строку. 'xargs' затем продолжает чтение ввода и выполнение команд, пока не закончится вход. 'xargs' запускает команду' grep' столько раз, сколько необходимо для введенного им ввода (из 'find' в этом примере). –

+0

Ах, моя ошибка, это использование grep для поиска в каждом файле.Я хотел просто фильтровать вывод find с grep –

2

Команда находка имеет -exec аргумент, который вы можете использовать для таких вещей, как это, вы могли бы просто сделать Grep непосредственно с помощью этого.

Например (from here, other good examples at this page):

find . -exec grep "www.athabasca" '{}' \; -print 
-1

Вы пытаетесь найти текст в файлах? Вы можете просто использовать Grep для этого ...

grep searchterm * 
30

Есть несколько способов, чтобы пройти список файлов, возвращаемых командой find к команде cat, хотя технически не все использования трубопроводов, и никто на самом деле трубы непосредственно до cat.

  1. Проще всего использовать кавычку:

    cat `find [whatever]` 
    

    Эквивалентно, можно использовать $() вместо обратные кавычки в некоторых оболочках, в том числе bash:

    cat $(find [whatever]) 
    

    Это менее переносимым, но является гнездовым.

    Оба синтаксиса берут вывод find и помещают его в командную строку cat. Это не очень хорошо работает, если find имеет слишком большой вывод (больше, чем может поместиться в командной строке), или если на выходе есть специальные символы (например, пробелы).

  2. Вы можете использовать -exec действие find «s, который выполняет команды для каждого файла, он находит:

    find [whatever] -exec cat {} \; 
    

    Это будет работать cat один раз для каждого файла, а не работает один экземпляр cat передачи его несколько имен файлов, которые могут быть неэффективными и могут не иметь поведения, которое вы хотите для некоторых команд (хотя это нормально для cat). Синтаксис также неудобен для ввода - вам нужно избежать точки с запятой, поскольку точка с запятой является специальной для оболочки!

    Некоторых версии find (в первую очередь в версии GNU) позволяют заменить ; с + использовать find «s режим приобщать для запуска меньше экземпляров cat.

    find [whatever] -exec cat {} + 
    

    Это будет пройти несколько имен файлов для каждого вызова cat, который может быть более эффективным. Обратите внимание, что это не гарантированно использует один вызов. Если командная строка слишком длинная, аргументы распределяются между несколькими вызовами cat. Для cat это, вероятно, не имеет большого значения, но для некоторых других команд это может изменить поведение нежелательными способами. В системах Linux ограничение длины командной строки довольно велико, поэтому разбиение на несколько вызовов довольно редко по сравнению с некоторыми другими операционными системами.

  3. Классический/портативный подход заключается в использовании xargs:

    find [whatever] | xargs cat 
    

    xargs запускает команду, указанную (cat, в данном случае), и добавляет аргументы, основанные на том, что он читает из стандартного ввода. Точно так же, как -exec с +, при необходимости он распадет командную строку. То есть, если find производит слишком большой объем вывода, он будет запускать cat несколько раз. Как упоминалось ранее в разделе о -exec, есть некоторые команды, в которых это расщепление может привести к поведению. Обратите внимание, что использование xargs, как это имеет место с пробелами в именах файлов, так как xargs просто использует пробелы в качестве разделителя.

  4. Самый надежный, портативный и эффективный метод также использует xargs:

    find [whatever] -print0 | xargs -0 cat 
    

    Флаг -print0 говорит find использовать \0 (нулевой символ) разделители между именами файлов и -0 флаг говорит xargs ожидать, что эти \0 разделители. Это очень похоже на подход -exec ... +, хотя и более портативный (но, к сожалению, более подробный).

-1

Чтобы получить список и увидеть содержимое всех abc.def файлов на сервере в каталогах/ГХИ и/JKL

find /ghi /jkl -type f -name abc.def 2> /dev/null -exec ls {} \; -exec cat {} \; 

Чтобы перечислить abc.def файлы, которые комментировали записи и отображать см эти записи в каталогах/ГХИ и/JKL

find /ghi /jkl -type f -name abc.def 2> /dev/null -exec grep -H ^# {} \; 
1

В Баш, то было бы целесообразно следующее:

find /dir -type f -print0 | xargs -0i cat {} | grep whatever 

Здесь вы найдете все файлы в каталоге /dir и безопасно проложите имена файлов в xargs, которые безопасно будут управлять grep.

Пропуск xargs не рекомендуется, если у вас много тысяч файлов в /dir; cat сломается из-за чрезмерной длины списка аргументов. xargs сортирует все для вас.

-print0 аргумент find зацепляется с -0 аргументом xargs обрабатывать имена файлов с пробелами правильно. Аргумент -i до xargs позволяет вставить имя файла, если требуется в командной строке cat. Скобки заменяются на имя файла, поданного в команду cat от find.

2

Вот мой выстрел для общего использования:

grep YOURSTRING `find .` 

Он будет печатать имя файла

0

Это работает для меня

find _CACHE_* | while read line; do 
    cat "$line" | grep "something" 
done 
9

Для достижения этого (с помощью Баша) Я хотел бы сделать следующим образом:

cat $(find . -name '*.foo') 

Это называется «подстановкой команд», и по умолчанию он лимитирует фид линии, что действительно удобно! больше

информация о here

0

Используйте ggrep.

ggrep -H -R -I "mysearchstring" * 

для поиска файла в UNIX, содержащий текст, расположенный в текущем каталоге или подкаталоге

4

Вот мой способ найти имена файлов, которые содержат некоторое содержание, что я заинтересован в, только один баш линия, которая хорошо обрабатывает пробелы в именах файлов тоже:

find . -name \*.xml | while read i; do grep '<?xml' "$i" >/dev/null; [ $? == 0 ] && echo $i; done 
1

Я использую что-то вроде этого:

find . -name <filename> -print0 | xargs -0 cat | grep <word2search4> 

«аргумент« find »и« -0 »аргумент« xargs »необходим для правильной обработки пробелов в путях/именах файлов.