Как передать список файлов, возвращаемых командой find для просмотра всех файлов

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

14 ответов

Решение
  1. Трубопровод к другому процессу (хотя это НЕ ПОЛУЧИТ то, что вы сказали, что пытаетесь сделать):

    command1 | command2
    

    Это отправит вывод command1 как ввод command2

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

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

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

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

    command2 `command1`
    

    например:

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

    (Обратите внимание, что это ЗАДНИЕ ЦИТАТЫ, а не обычные кавычки (под тильдой ~ на моей клавиатуре).) Это отправит вывод command1 в command2 в качестве аргументов командной строки. Обратите внимание, что имена файлов, содержащие пробелы (переводы строк и т. Д.), Будут разбиты на отдельные аргументы.

find . -print | xargs grep something

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

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


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

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

Оба эти проблемы с xargs без -0 вариант. Следовательно, вы могли бы разумно написать:

find . -exec grep something {} +

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

  1. Самое простое - это использовать backticks (`):

    cat `find [whatever]`
    

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

  2. В некоторых снарядах, в том числе bashможно использовать $() вместо кавычек:

    cat $(find [whatever])
    

    Это менее переносимо, но является вложенным. Помимо этого, он имеет почти те же предостережения, что и кавычки.

  3. Потому что выполнение других команд для найденного является обычным findнайти есть -exec действие, которое выполняет команду для каждого найденного файла:

    find [whatever] -exec cat {} \;
    

    {} является заполнителем для имени файла, а \; отмечает конец команды (возможно выполнение других действий после -exec.)

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

  4. Некоторые версии find (в частности, версия GNU) позволит вам заменить ; с + использовать -execрежим добавления для запуска меньшего количества экземпляров cat:

    find [whatever] -exec cat {} +
    

    Это передаст несколько имен файлов для каждого вызова cat, который может быть более эффективным.

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

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

    find [whatever] | xargs cat
    

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

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

    find [whatever] -print0 | xargs -0 cat
    

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

Для этого (используя bash) я бы сделал следующее:

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

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

больше информации здесь

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

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

или что-то типа того

Вот мой способ найти имена файлов, которые содержат интересующий меня контент, всего лишь одну строку bash, которая также хорошо обрабатывает пробелы в именах файлов:

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

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

Например ( отсюда, другие хорошие примеры на этой странице):

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

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

grep YOURSTRING `find .`

Это напечатает имя файла

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

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

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

В bash было бы целесообразно следующее:

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,

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

ggrep -H -R -I "mysearchstring" *

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

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

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

Это напечатает имя и содержимое файлов только рекурсивно.

find . -type f -printf '\n\n%p:\n' -exec cat {} \;

Для просмотра и просмотра содержимого всех файлов abc.def на сервере в каталогах /ghi и /jkl

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

Чтобы просмотреть список файлов abc.def с комментариями и отображением, см. Эти записи в каталогах /ghi и /jkl

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

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

grep searchterm *
Другие вопросы по тегам