Piping находит результаты в grep для быстрого исключения каталогов
Я успешно использую find для создания списка всех файлов в текущем подкаталоге, за исключением тех, которые находятся в кэш-памяти подкаталога. Вот мой первый бит кода:
find . -wholename './cach*' -prune -o -print
Теперь я хочу передать это в команду grep. Похоже, это должно быть простым:
find . -wholename './cach*' -prune -o -print | xargs grep -r -R -i "samson"
... но это возвращает результаты, которые в основном из каталога кеша. Я попытался удалить ссылку xargs, но это делает то, что вы ожидаете, запуская grep по тексту имен файлов, а не по самим файлам. Моя цель - найти "samson" в любых файлах, которые не кэшируются.
Я, вероятно, обойду эту проблему, просто используя удвоенные greps в этом случае, но мне очень любопытно, почему этот однострочный интерфейс ведет себя таким образом. Мне бы хотелось услышать мысли о том, как изменить его, все еще используя эти две команды (так как есть преимущество в скорости таким образом).
(Это в CentOS 5, кстати.)
Ответы
Ответ 1
Соответствие wholename
может быть причиной, по которой оно все еще включает файлы "cache". Если вы выполняете команду find
в каталоге, который содержит папку "cache", он должен работать. Если нет, попробуйте заменить его на -name '*cache*'
.
Кроме того, вам не нужен -r
или -r
для grep
, который сообщает ему, что он рекурсирует через каталоги, но вы проверяете отдельные файлы.
Вы можете обновить свою команду, используя версию с поддержкой протокола или одну команду:
find . -name '*cache*' -prune -o -print0 | xargs -0 grep -il "samson"
или
find . -name '*cache*' -prune -o -exec grep -iq "samson" {} \; -print
Примечание. -l
в первой команде сообщает grep
"перечислить файл", а не соответствующую строку (строки). -q
во втором делает то же самое; он сообщает grep
ответить тихо, поэтому find
будет просто печатать имя файла.
Ответ 2
Используйте параметр -exec
для поиска вместо того, чтобы связывать их с другой командой. Оттуда вы можете использовать grep "samson" {} \;
для поиска samson в каждом указанном файле.
Например:
find . -wholename './cach*' -prune -o -exec grep "samson" "{}" +
Ответ 3
Вы сказали grep
самому себе: (дважды! -r
и -r
являются синонимами). Поскольку один из аргументов, которые вы передаете, .
(верхний каталог), grep
выполняет поиск в каждом файле (некоторые из них дважды или даже больше, если они находятся в подкаталогах).
Если вы собираетесь использовать find
и grep
, сделайте следующее:
find . -path './cach*' -prune -o -print0 | xargs -0 grep -i "samson"
Используя -print0
и -0
, ваш script работает даже с именами файлов, которые содержат пробелы или знаки пунктуации.
Однако вам, вероятно, не нужно беспокоиться о find
здесь, поскольку GNU grep способен исключать каталоги:
grep -R --exclude-dir='cach*' -i "samson" .
(Это также исключает ./deeply/nested/directory/cache
. Если вы хотите только исключить каталоги кешей на верхнем уровне, используйте find
, как и вы.)