Как передать список файлов, возвращаемых командой find для просмотра всех файлов
Я делаю find
а затем получить список файлов. Как мне передать это в другую утилиту, например cat
(так что cat отображает содержимое всех этих файлов) и в основном нужно grep
что-то из этих файлов.
14 ответов
Трубопровод к другому процессу (хотя это НЕ ПОЛУЧИТ то, что вы сказали, что пытаетесь сделать):
command1 | command2
Это отправит вывод command1 как ввод command2
-exec
наfind
(это будет делать то, что вы хотите сделать, - но конкретноfind
)find . -name '*.foo' -exec cat {} \;
(Все между
find
а также-exec
предикаты поиска, которые вы уже использовали{}
заменит конкретный файл, который вы нашли в команде (cat {}
в этом случае);\;
это закончить-exec
команда.)отправлять вывод одного процесса в качестве аргументов командной строки другому процессу
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
делает, но с рядом преимуществ:
- Вам не нужно беспокоиться о нечетных символах в именах файлов.
- Вам не нужно беспокоиться о том, что команда вызывается с нулевыми именами файлов.
Оба эти проблемы с xargs
без -0
вариант. Следовательно, вы могли бы разумно написать:
find . -exec grep something {} +
Есть несколько способов передать список файлов, возвращаемых find
командовать cat
команда, хотя технически не все используют трубопроводы, и ни один из них на самом деле не направляет cat
,
Самое простое - это использовать backticks (
`
):cat `find [whatever]`
Это берет вывод
find
и эффективно помещает его в командную строкуcat
, Это не работает хорошо, еслиfind
имеет слишком много выходных данных (больше, чем может поместиться в командной строке) или если выходные данные содержат специальные символы (например, пробелы).В некоторых снарядах, в том числе
bash
можно использовать$()
вместо кавычек:cat $(find [whatever])
Это менее переносимо, но является вложенным. Помимо этого, он имеет почти те же предостережения, что и кавычки.
Потому что выполнение других команд для найденного является обычным
find
найти есть-exec
действие, которое выполняет команду для каждого найденного файла:find [whatever] -exec cat {} \;
{}
является заполнителем для имени файла, а\;
отмечает конец команды (возможно выполнение других действий после-exec
.)Это будет работать
cat
один раз для каждого отдельного файла, а не для запуска одного экземпляраcat
передавая ему несколько имен файлов, которые могут быть неэффективными и могут не иметь желаемого поведения для некоторых команд (хотя это хорошо дляcat
). Синтаксис также неудобен для ввода - вам нужно избегать точки с запятой, потому что точка с запятой является особенной для оболочки!Некоторые версии
find
(в частности, версия GNU) позволит вам заменить;
с+
использовать-exec
режим добавления для запуска меньшего количества экземпляровcat
:find [whatever] -exec cat {} +
Это передаст несколько имен файлов для каждого вызова
cat
, который может быть более эффективным.Обратите внимание, что это не гарантирует использование одного вызова, однако. Если командная строка будет слишком длинной, то аргументы будут распределены по нескольким вызовам
cat
, Заcat
это, вероятно, не имеет большого значения, но для некоторых других команд это может изменить поведение нежелательным образом. В системах Linux ограничение длины командной строки довольно велико, поэтому разбиение на несколько вызовов довольно редко по сравнению с некоторыми другими операционными системами.Классический / портативный подход заключается в использовании
xargs
:find [whatever] | xargs cat
xargs
запускает указанную команду (cat
в данном случае) и добавляет аргументы, основанные на том, что он читает со стандартного ввода. Как-exec
с+
это разрушит командную строку при необходимости. То есть еслиfind
выдает слишком много продукции, она будет работатьcat
многократно. Как уже упоминалось в разделе о-exec
ранее, есть некоторые команды, где это разделение может привести к другому поведению. Обратите внимание, что с помощьюxargs
как это имеет проблемы с пробелами в именах файлов, какxargs
просто использует пробел в качестве разделителя.Самый надежный, портативный и эффективный метод также использует
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 *