Как передать список файлов, возвращаемых командой find, чтобы просмотреть все файлы
Я делаю find
, а затем получаю список файлов. Как мне передать его на другую утилиту, например, cat
(так что cat отображает содержимое всех этих файлов) и в основном нужно grep
что-то из этих файлов.
Ответы
Ответ 1
-
Трубопровод к другому процессу (хотя это НЕ будет выполнено, что вы сказали, что вы пытаетесь сделать):
command1 | command2
Это отправит вывод команды 1 в качестве ввода команды2
-
-exec
на find
(это будет делать то, что вы хотите сделать, но имеет значение для find
)
find . -name '*.foo' -exec cat {} \;
(Все между find
и -exec
- это предикаты поиска, которые вы уже использовали. {}
заменит конкретный файл, который вы нашли в команде (cat {}
в этом случае); \;
- завершите команду -exec
.)
-
отправить вывод одного процесса в качестве аргументов командной строки в другой процесс
command2 `command1`
например:
cat `find . -name '*.foo' -print`
(Обратите внимание: это BACK-QUOTES не обычные кавычки (под тильдой ~ на моей клавиатуре).)
Это отправит вывод command1
в command2
в качестве аргументов командной строки. Обратите внимание, что имена файлов, содержащие пробелы (новые строки и т.д.), Будут разбиты на отдельные аргументы.
Ответ 2
Современная версия
POSIX 2008 добавил маркер +
чтобы find
что означает, что теперь он автоматически группирует столько файлов, сколько разумно, в одно выполнение команды, очень похоже на xargs
, но с рядом преимуществ:
- Вам не нужно беспокоиться о нечетных символах в именах файлов.
- Вам не нужно беспокоиться о том, что команда вызывается с нулевыми именами файлов.
Обе эти проблемы xargs
с xargs
без опции -0
(а запуск даже с 0 именами файлов - это проблема с опцией -0
или без -0
). Кроме того, эта запись сокращает количество процессов, а не то, что вы, скорее всего, будете измерять разницу в производительности. Следовательно, вы могли бы разумно написать:
find . -exec grep something {} +
Классическая версия
find . -print | xargs grep something
Если вы работаете в Linux или используете команды GNU find
и xargs
, то используйте -print0
с find
и -0
с xargs
для обработки имен файлов, содержащих пробелы и другие нечетные символы.
find . -print0 | xargs -0 grep something
Если вам не нужны имена файлов (только текст), добавьте соответствующую опцию в grep
(обычно -h
для подавления "заголовков"). Чтобы абсолютно гарантировать, что имя файла напечатано с помощью grep
(даже если найден только один файл или при последнем вызове grep
задано только 1 имя файла), добавьте /dev/null
в командную строку xargs
, чтобы всегда было быть как минимум два имени файла.
Ответ 3
Есть несколько способов передать список файлов, возвращаемых командой find
команде cat
, хотя технически не все используют конвейерную связь, и на самом деле ни один из них не направляет напрямую в cat
.
-
Самое простое - это использовать обратные галочки ('
):
cat 'find [whatever]'
Это берет вывод find
и эффективно помещает его в командную строку cat
. Это не работает, если find
имеет слишком много выходных данных (больше, чем может поместиться в командной строке) или если выходные данные содержат специальные символы (например, пробелы).
-
В некоторых оболочках, включая bash
, можно использовать $()
вместо обратных галочек:
cat $(find [whatever])
Это менее переносимо, но является вложенным. Помимо этого, он имеет почти те же предостережения, что и кавычки.
-
Поскольку выполнение других команд для найденного является обычным использованием find
, find имеет действие -exec
которое выполняет команду для каждого -exec
файла:
find [whatever] -exec cat {} \;
{}
Является заполнителем для имени файла, а \;
отмечает конец команды (возможны другие действия после -exec
.)
Это будет запускать cat
один раз для каждого отдельного файла, а не запускать один экземпляр cat
передавая ему несколько имен файлов, что может быть неэффективно и может не соответствовать желаемому поведению некоторых команд (хотя это хорошо для cat
). Синтаксис также неудобен для ввода - вам нужно избегать точки с запятой, потому что точка с запятой является особенной для оболочки!
-
Некоторые версии find
(особенно версия GNU) позволяют вам заменить ;
+
использовать -exec
добавления -exec
для запуска меньшего количества экземпляров cat
:
find [whatever] -exec cat {} +
Это передаст несколько имен файлов каждому вызову cat
, что может быть более эффективным.
Обратите внимание, что это не гарантирует использовать один вызов, однако. Если командная строка будет слишком длинной, то аргументы будут распределены по нескольким вызовам cat
. Для cat
это, вероятно, не имеет большого значения, но для некоторых других команд это может изменить поведение нежелательным образом. В системах Linux ограничение длины командной строки довольно велико, поэтому разбиение на несколько вызовов довольно редко по сравнению с некоторыми другими операционными системами.
-
Классический/переносимый подход заключается в использовании xargs
:
find [whatever] | xargs cat
xargs
запускает указанную команду (в данном случае cat
) и добавляет аргументы на основе того, что она читает из stdin. Точно так же, как -exec
с +
, это сломает командную строку при необходимости. То есть, если find
выдает слишком много информации, она будет запускать cat
несколько раз. Как упоминалось в разделе о -exec
ранее, есть некоторые команды, в которых это разделение может привести к другому поведению. Обратите внимание, что при использовании xargs
подобных этому, xargs
проблемы с пробелами в именах файлов, поскольку xargs
просто использует пробел в качестве разделителя.
-
Самый надежный, переносимый и эффективный метод также использует xargs
:
find [whatever] -print0 | xargs -0 cat
Флаг -print0
указывает, что find
использует разделители \0
(нулевой символ) между именами файлов, а флаг -0
сообщает xargs
следует ожидать этих разделителей \0
. Это поведение в значительной степени идентично поведению -exec
... +
, хотя и более переносимо (но, к сожалению, более многословно).
Ответ 4
Чтобы достичь этого (используя bash), я бы сделал следующее:
cat $(find . -name '*.foo')
Это называется "подстановкой команд", и по умолчанию он лимитирует фид строки, который действительно удобен!
больше информации здесь
Ответ 5
Мне нравится работа для оболочки script для меня:
for file in 'find -name *.xml'
do
grep 'hello' file
done
или что-то в этом роде
Ответ 6
Здесь мой способ найти имена файлов, которые содержат некоторый контент, который мне интересен, только одна строка bash, которая прекрасно обрабатывает пробелы в именах файлов:
find . -name \*.xml | while read i; do grep '<?xml' "$i" >/dev/null; [ $? == 0 ] && echo $i; done
Ответ 7
Я использую что-то вроде этого:
find . -name <filename> -print0 | xargs -0 cat | grep <word2search4>
"-print0
" аргумент для аргумента "find" и "-0
" для "xargs" необходим для правильной обработки пробелов в путях/именах файлов.
Ответ 8
В команде find есть аргумент -exec, который вы можете использовать для таких вещей, вы можете просто использовать grep напрямую, используя это.
Например (отсюда, другие хорошие примеры на этой странице):
find . -exec grep "www.athabasca" '{}' \; -print
Ответ 9
В 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
.
Ответ 10
Вот мой снимок для общего использования:
grep YOURSTRING `find .`
Он выведет имя файла
Ответ 11
Это работает для меня
find _CACHE_* | while read line; do
cat "$line" | grep "something"
done
Ответ 12
Используйте ggrep.
ggrep -H -R -I "mysearchstring" *
для поиска файла в unix, содержащего текст, расположенный в текущем каталоге или подкаталоге
Ответ 13
Вы пытаетесь найти текст в файлах? Вы можете просто использовать grep для этого...
grep searchterm *
Ответ 14
Чтобы просмотреть и просмотреть содержимое всех файлов 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 ^# {} \;