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

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

14 ответов


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

    command1 | command2
    

    это отправит вывод command1 в качестве ввода command2

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

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

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

  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 без . Следовательно, вы могли бы разумно написать:

find . -exec grep something {} +

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

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

    cat `find [whatever]`
    

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

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

    cat $(find [whatever])
    

    это менее портативный, но nestable. Помимо этого, у него есть почти те же предостережения, что и backticks.

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

    find [whatever] -exec cat {} \;
    

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

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

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

    find [whatever] -exec cat {} +
    

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

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

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

    find [whatever] | xargs cat
    

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

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

    find [whatever] -print0 | xargs -0 cat
    

    на -print0 флаг говорит find использовать (нулевой символ) разделители между именами и -0 флаг говорит xargs ожидать, что эти разделители. Это имеет почти идентичное поведение с -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 . -name <filename> -print0 | xargs -0 cat | grep <word2search4>

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


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

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

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

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

grep YOURSTRING `find .`

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


в bash было бы уместно следующее:

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

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

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

на до find сетки с до xargs для правильной обработки имен файлов с пробелами. The до xargs позволяет вставить имя файла, где это необходимо в cat командная строка. Скобки заменяются именем файла, переданным в С find.


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

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

использовать ggrep.

ggrep -H -R -I "mysearchstring" *

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


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

grep searchterm *

чтобы перечислить и просмотреть содержимое всех 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 ^# {} \;