Почему я не могу найти? Помогает только кошачья находка. Как я вижу, программа grep могла видеть некоторый контекст, в котором выполняется каждая команда. Но для новичка, как я, это нелогично. Когда задано с аргументом, grep может искать файлы, но когда оно с pipe (|) - не может.

2 ответа2

3

Команда find создает список путей, которые соответствуют критериям поиска, в данном случае это имя с расширением .ebuild . (Но незначительный спор: вам нужны кавычки вокруг подстановочного знака, чтобы оболочка пропустила его, чтобы найти, не пытаясь сначала его развернуть.) Если вы передадите это в grep , все, что вы делаете, это фильтруете этот список имен, а не содержимое этих файлов.

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

Более простой способ сделать то, что вы хотите, это использовать подстановку команд для прямой передачи имен в grep :

grep RESTRICT $(find /usr/portage -name "e.build")
1

Чтобы выразить команду Николь Гамильтон в более сжатой форме, вы можете использовать флаг -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 секунды.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .