Как ограничить grep поиском только тех файлов, которые вы хотите

У нас довольно большая и сложная файловая система, и я пытаюсь создать список файлов, содержащих определенную текстовую строку. Это должно быть просто, но мне нужно исключить каталоги './svn' и './pdv' (и, возможно, другие) и просматривать только файлы типа *.p, *.w или .i< /эм>.

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

Обычно мы ищем файловую систему, используя:

find . -name "*.[!r]*" -exec grep -i -l "search for me" {} \;

Это работает, но мне приходится использовать программу для исключения нежелательных каталогов, поэтому она работает очень медленно.

После просмотра тем здесь: поток переполнения стека

Я решил попробовать несколько других подходов:

grep -ilR "search for me" . --exclude ".svn" --excluse "pdv" --exclude "!.{p,w,i*}" 

Исключает каталоги './svn', но не каталоги './pdv'. Не ограничивает просматриваемые файлы.

grep -ilR "search for me" . --exclude ".svn" --excluse "pdv" --include "*.p" 

Исключает каталоги './svn', но не каталоги './pdv'. Не ограничивает просматриваемые файлы.

find . -name "*.[!r]*" -exec grep -i -l ".svn" | grep -i -l "search for me" {} \;

Я даже не могу заставить это (или его варианты) успешно работать.

find . ! -name "*.svn*" -prune -print -exec grep -i -l "search for me" {} \;

Ничего не возвращает. Похоже, он останавливается, как только находит каталог .svn.


person Colin    schedule 18.08.2011    source источник
comment
В явном виде я ищу все файлы, соответствующие любому из .p,.w или .i, за исключением каталогов с именами .svn и pdv. Большое спасибо   -  person Colin    schedule 18.08.2011
comment
В ваших примерах --excluse "pdv" (обратите внимание на опечатку s/d) в обоих случаях, и вы жалуетесь на то, что это конкретное условие не работает... просто проверка опечатки не является основной проблемой.   -  person geronime    schedule 19.08.2011
comment
Ну, я думаю, что D'Oh! хорошее начало. Спасибо, что заметили это.   -  person Colin    schedule 19.08.2011
comment
@geronime, я только что попробовал этот пример с исправленной опечаткой (надеюсь). Строка поиска: grep -ilR "run" . --exclude ".svn" --exclude "pdv" --exclude "!.{p,w,i*}". К сожалению, поскольку набор результатов теперь включает как .svn/text-base/jr83144.p.svn-base, так и pdv/cm/backupds.i, я не думаю, что это сработало. Большое спасибо   -  person Colin    schedule 19.08.2011
comment
вы скорее пробовали параметр --exclude-dir? Это на самом деле проблема, я думаю. См. руководство grep.   -  person geronime    schedule 19.08.2011
comment
Чтобы исключить каталоги: find . \( \( -name .svn -o -name pdv \) -type d -prune \) -o \( -name '*.[pwi]' -exec grep ... {} + \)   -  person Adrian Pronk    schedule 19.08.2011
comment
@geronime, я пробовал --exclude-dir, но он не зарегистрировался. Ни он, ни --exclude в инструкции не указаны.   -  person Colin    schedule 19.08.2011
comment
@adrian, кажется, это сработало, спасибо.   -  person Colin    schedule 19.08.2011
comment
Просто хотел сказать спасибо всем вам за вашу помощь. Даже если ответ не сработал, он дает мне хорошее представление о том, как выполнить поиск и поиск работы.   -  person Colin    schedule 19.08.2011
comment
@Colin: Я вижу, ты говорил не о Linux. --exclude и --exclude-dir — это расширенные опции grep, реализованные в Linux.   -  person geronime    schedule 19.08.2011


Ответы (4)


Как насчет чего-то вроде:

find . \( \( -name .svn -o -name pdv \) -type d -prune \) -o \( -name '*.[pwi]' -type f -exec grep -i -l "search for me" {} + \)

Это будет:
- игнорировать содержимое каталогов с именами .svn и pdv
- файлы grep (и символические ссылки на файлы) с именами *.[pwi]

Параметр + после exec означает объединение в одну команду столько файлов, сколько поместится в командной строке (примерно 1 миллион символов в Linux). Это может серьезно ускорить обработку, если вам нужно перебирать тысячи файлов.

person Adrian Pronk    schedule 19.08.2011

Следующая команда находит только файлы *.rb, содержащие строку require 'bundler/setup', и исключает поиск в каталогах .git и .bundle. Я думаю, это тот же вариант использования.

grep -ril --exclude-dir .git --exclude-dir .bundle \
  --include \*.rb "^require 'bundler/setup'$" .

Проблема была с заменой параметров --exclude и --exclude-dir, я полагаю. См. руководство grep(1).

Также обратите внимание, что параметры exclude/include принимают только GLOB, а не регулярные выражения, поэтому диапазон суффиксов из одного символа можно задать с одним параметром --include, но для более сложных условий потребуется больше параметров:

--include \*.[pwi] --include \*.multichar_sfx ...
person geronime    schedule 19.08.2011

Вы можете попробовать следующее:

find path_starting_point -type f | grep regex_to_filter_file_names | xargs grep regex_to_find_inside_matched_files
person Heisenbug    schedule 18.08.2011
comment
Я пробовал это, но я не могу правильно использовать regex_to_filter_file_names. Я пробовал find . -type f | grep .*\.p | xargs -il grep "run", но он возвращает файлы, заканчивающиеся на .ixx, а также заканчивающиеся на .p. - person Colin; 18.08.2011
comment
может быть grep '\.\[pwi\]$' для соответствия файлам, оканчивающимся на суффикс .p, .w или .i - person geronime; 19.08.2011

person    schedule
comment
Я также попробовал это, но снова не могу заставить регулярное выражение работать. Простое использование простого примера find . -name ".*\.i" для проверки концепции не возвращает никаких значений. - person Colin; 18.08.2011