2012-03-05 23:28:16 +0000 2012-03-05 23:28:16 +0000
148
148

Как игнорировать определенные имена файлов с помощью "найти"?

Одна из моих любимых команд BASH:

find . -name '*.*' -exec grep 'SearchString' {} /dev/null \;

, которая ищет содержимое всех файлов в текущем каталоге и ниже указанного SearchString. Как разработчик, это иногда пригодилось.

Однако, благодаря моему текущему проекту и структуре моей кодовой базы, я хотел бы сделать эту команду BASH еще более продвинутой, не осуществляя поиск любых файлов, которые находятся в каталоге, содержащем “.svn” или ниже, или любых файлов, которые заканчиваются на “.html”

Страница MAN для поиска сбивает меня с толку, хотя и смущает. Я попробовал использовать -prune, и это дало мне странное поведение. Пытаясь пропустить только .html страницы (для начала), я попытался :

find . -wholename './*.html' -prune -exec grep 'SearchString' {} /dev/null \;

и не получил того поведения, на которое надеялся. Я думаю, что, возможно, я упускаю суть -prune. Ребята, не могли бы вы мне помочь?

Спасибо.

Ответы (3)

209
209
209
2012-03-06 00:40:37 +0000

Вы можете использовать функцию поиска negate (!), чтобы не совпадать с файлами с определенными именами:

find . ! -name '*.html' ! -path '*.svn*' -exec grep 'SearchString' {} /dev/null \;

Так что если имя заканчивается на .html или содержит .svn где-нибудь в пути, оно не будет совпадать, и поэтому выполнение не будет выполнено.

12
12
12
2012-03-06 13:54:15 +0000

У меня уже давно одна и та же проблема, и есть несколько решений, которые могут быть применимы в разных ситуациях:

  • ack-grep это своего рода “grep разработчика”, который по умолчанию пропускает каталоги контроля версий и временные файлы. Страница man объясняет, как искать только определенные типы файлов и как определить свой собственный .
  • собственные опции grep и --exclude могут быть очень легко использованы для пропуска каталогов globs и single файлов (к сожалению, нет глобуса для каталогов).
  • --exclude-dir должны работать, но вышеприведенные опции, вероятно, будут менее хлопотными в долгосрочной перспективе.
9
9
9
2012-03-06 03:29:21 +0000

Следующая команда find выполняет обрезку каталогов, имена которых contain .svn, хотя и не опускается в каталог, но печатается имя обрезного пути …(-name '*.svn' является причиной!) …

Вы можете отфильтровать имена каталогов по этой команде: grep -d skip, который беззвучно пропускает такие вводимые “имена каталогов”.

С помощью GNU grep вы можете использовать -H вместо /dev/null. В качестве небольшой побочной проблемы: может быть намного быстрее, чем `\;`, например, для 1 миллиона однострочных файлов, при использовании `\;` это заняло _4m20s_, при использовании это заняло только 1.2s.

Следующий метод использует xargs вместо -exec и предполагает, что ни в одном из ваших файлов имя нет новых строк \n. В том виде, в котором он используется здесь, xargs во многом совпадает с найденным “.

xargs могут передавать имена файлов, которые содержат последовательные пробелы, изменяя входной разделитель на '\n' с опцией -d.

Это исключает директории, имена которых contain .svn и greps только файлы, которые не заканчиваются на .html.

find . \( -name '*.svn*' -prune -o ! -name '*.html' \) |
   xargs -d '\n' grep -Hd skip 'SearchString'