Почему я не могу найти? Помогает только кошачья находка. Как я вижу, программа grep могла видеть некоторый контекст, в котором выполняется каждая команда. Но для новичка, как я, это нелогично. Когда задано с аргументом, grep может искать файлы, но когда оно с pipe (|) - не может.
2 ответа
Команда find
создает список путей, которые соответствуют критериям поиска, в данном случае это имя с расширением .ebuild
. (Но незначительный спор: вам нужны кавычки вокруг подстановочного знака, чтобы оболочка пропустила его, чтобы найти, не пытаясь сначала его развернуть.) Если вы передадите это в grep
, все, что вы делаете, это фильтруете этот список имен, а не содержимое этих файлов.
В отличие от этого, конструкция cat $(find ...)
использует подстановку команд (это часть $(...)
), чтобы вставить результат поиска (список генерируемых им путей) обратно в командную строку в качестве аргументов для cat
, заставляя cat
записать содержимое этих файлов в стандартный вывод и в grep
.
Более простой способ сделать то, что вы хотите, это использовать подстановку команд для прямой передачи имен в grep
:
grep RESTRICT $(find /usr/portage -name "e.build")
Чтобы выразить команду Николь Гамильтон в более сжатой форме, вы можете использовать флаг -exec для команды find.
find /usr/portage -name '*.ebuild' -exec grep RESTRICT {} \;
При этом имена сопоставляемых файлов передаются в grep, а фигурные скобки заменяются именем файла. '\;' сбежавший ';' это используется для обозначения конца команды.
Производительность @garyjohn
Это сравнение разных моментов времени выполнения команды find. Все эти тесты проводились с использованием недавнего снимка portage (http://distfiles.gentoo.org/snapshots/portage-latest.tar.bz2). Я побежал "найти". и 'grep -Rni. «. Прежде чем приступить к планированию этих тестов, я надеюсь, что кэширование диска и оперативной памяти должно быть одинаковым во всех тестах.
Вот время для двух команд:
% time grep RESTRICT $(find . -name "*.ebuild") > /dev/null
grep --color RESTRICT $(find . -name "*.ebuild") > /dev/null 0.05s user 0.13s system 95% cpu 0.192 total
% time find . -name "*.ebuild" -exec grep RESTRICT {} \; > /dev/null
find . -name "*.ebuild" -exec grep RESTRICT {} \; > /dev/null 0.68s user 2.63s system 14% cpu 22.523 total
Как вы можете видеть, метод cat намного быстрее завершается примерно за 5% времени моего примера.
Однако, если команда find возвращает слишком много файлов, мы запускаем предел оболочки с длиной одной команды. Это приведет к сбою команды.
% time grep RESTRICT $(find . -name "*") > /dev/null
zsh: argument list too long: grep
grep --color RESTRICT $(find . -name "*") > /dev/null 0.34s user 0.04s system 99% cpu 0.374 tota
Чтобы увидеть это ограничение на использование вашей системы.
getconf ARG_MAX
Вот найти бег с тем же шаром. Обратите внимание, что это занимает очень много времени, но оно успешно завершается.
% time find . -name "*" -exec grep RESTRICT {} \; > /dev/null
find . -name "*" -exec grep RESTRICT {} \; > /dev/null 2.52s user 11.00s system 12% cpu 1:47.67 total
Оптимальный способ запуска этой команды в safley - использовать xargs.
% time find . -name "*" -print0 | xargs -0 grep RESTRICT > /dev/null
find . -name "*" -print0 0.16s user 0.29s system 51% cpu 0.886 total
xargs -0 grep RESTRICT > /dev/null 0.33s user 0.59s system 100% cpu 0.915 total
Используя xargs, можно пролистать все дерево портежей (~ 159995 файлов, 724M) всего за 2 секунды.