Як я можу виключити каталоги з grep -R?


668

Я хочу перейти всі підкаталоги, крім каталогу "node_modules".



14
Просто введіть "man grep", і ви побачите параметри --exclude, і --exclude-dir, перелічені там - із заголовка цього питання, я припускаю, що ви вже знали про grep ...
arcseldon

35
Якщо ви шукаєте код у сховищі git і node_modulesє у вашому .gitignore, git grep "STUFF"це найпростіший спосіб. git grepшукає відслідковані файли у робочому дереві, ігноруючи все з.gitignore
0xcaff

2
Приклад для вузла: grep -R --exclude-dir={node_modules,bower_components} "MyString" | cut -c1-"$COLUMNS"- далі ви завжди можете це псевдонімом називати "nodegrep" або будь-яким іншим і використовувати аргумент команди як введення рядка ..
bshea

Відповіді:


394

РІШЕННЯ 1 (комбінувати findта grep)

Мета цього рішення полягає не в роботі з grepпродуктивністю, а в демонстрації портативного рішення: також слід працювати з zaposbox або GNU версією старшою за 2,5.

Використовуйте findдля виключення каталогів foo та bar:

find /dir \( -name foo -prune \) -o \( -name bar -prune \) -o -name "*.sh" -print

Потім поєднайте findі нерекурсивне використання grep, як портативного рішення:

find /dir \( -name node_modules -prune \) -o -name "*.sh" -exec grep --color -Hn "your text to find" {} 2>/dev/null \;

РІШЕННЯ 2 (рекурсивне використання grep):

Ви вже знаєте це рішення, але я додаю його, оскільки це останнє та ефективне рішення. Зауважте, що це менш портативне рішення, але зручніше для людини.

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

Щоб виключити кілька каталогів, використовуйте --exclude-dirяк:

--exclude-dir={node_modules,dir1,dir2,dir3}

РІШЕННЯ 3 (Ag)

Якщо ви часто шукаєте код, Ag (The Silver Searcher) - це набагато швидша альтернатива grep, яка налаштована для пошуку коду. Наприклад, він автоматично ігнорує файли та каталоги, перелічені в .gitignore, тому вам не доведеться продовжувати передавати ті самі громіздкі параметри виключення до grepабо find.


2
ця комбінація шукає швидше, --exclude-dir=dirі вона показує результати з кольорами - легко читати
Максим Єфремов

27
"це поєднання" find ... -execне швидше, ніж grep --exclude-dirдля мене. Величезна перевага в Grep (приблизно в п'ять разів швидше 26K + файли, відфільтрованих 38K + на HDD), якщо не замінити \;з +для пошуку / ехес комбо. Тоді греп "лише" приблизно на 30% швидше. Синтаксис грепу також читається людиною :).
Kjell Andreassen

Домовились, оскільки це очевидно. У деяких службових скриньках немає команди GREP.
hornetbzz

10
відзначаючи також , що ви можете виключити мультиплікатор з--exclude-dir={dir1,dir2}
Suh

4
Я не в останню чергу здивований, що node_modulesце канонічний приклад.
pdoherty926

982

Останні версії GNU Grep (> = 2.5.2 ) передбачають:

--exclude-dir=dir

який виключає каталоги, що відповідають шаблону, dirз рекурсивних пошуків у каталозі.

Отже, ви можете зробити:

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

Більш детальну інформацію про синтаксис та використання див

Для старих GNU Greps та POSIX Grep використовуйте, findяк пропонується в інших відповідях.

Або просто скористайтеся ack( Edit : або The Silver Searcher ) і будьте з цим!


4
@Manocho: Якщо ви думаєте, що ackце чудово, спробуйте Silver Searcher і побачите збільшення швидкості!
Johnsyweb

30
Синтаксис для нетерплячих: --exclude-dir=dirвикористовує grepсхеми регулярних виразів, а не глобулювання файлів оболонки. Шаблони працюють на шляхах, що відносяться до поточного каталогу. Тому використовуйте візерунок --exclude-dir=dir, а не --exclude-dir="/root/dir/*".
tanius

15
Якщо ви хочете виключити кілька пошукових запитів із пошуку, чи є кращий варіант, ніж використовувати $ grep -r --exclude-dir=dir1 --exclude-dir=dir2 "string" /path/to/search/dir:?
Даршан Чадхарі

4
Я, мабуть, витратив на це занадто багато часу, ніж будь-яка розумна людина, але я не можу за все життя зрозуміти, як виключити підкаталог із пошуку - grep -r --exclude-dir=public keyword .працює, але grep -r --exclude-dir='public/dist' keyword .це не так. Я спробував додати подстановочні символи регулярних виразів, уникнути символів тощо, але, здається, нічого не допоможе.
dkobozev

72
Виключіть декілька каталогів так:grep -r "Request" . --exclude-dir={node_modules,git,build}
maverick97

77

Якщо ви хочете виключити кілька каталогів :

"r" для рекурсивного, "l" для друку лише імен файлів, що містять відповідність, і "i" для ігнорування відмінностей регістру:

grep -rli --exclude-dir={dir1,dir2,dir3} keyword /path/to/search

Приклад: Я хочу знайти файли, які містять слово "привіт". Я хочу шукати у всіх моїх каталогах Linux, окрім proc каталог, завантажувальний каталог, каталог sys та кореневий каталог:

grep -rli --exclude-dir={proc,boot,root,sys} hello /

Примітка. Наведений вище приклад має бути кореневим

Примітка 2 (відповідно до @skplunkerin): не додайте пробілів після коми в {dir1,dir2,dir3}


5
ПРИМІТКА: не додайте пробілів після коми в{dir1,dir2,dir3}
skplunkerin

Дякую, зручно під час перегляду робочого простору SVN:grep -Irsn --exclude-dir=.svn 'foo' .
RAM237

1
Ви можете просто надати --exclude-dirможливість кілька разів.
Вальф

44

Цей синтаксис

--exclude-dir={dir1,dir2}

розширюється на оболонку (наприклад, Bash), а не grepна:

--exclude-dir=dir1 --exclude-dir=dir2

Котирування не дозволить розширити оболонку, тому це не буде працювати:

--exclude-dir='{dir1,dir2}'    <-- this won't work

Шаблони, з --exclude-dirякими використовуються, є однаковими шаблонами, описаними на сторінці "man" для --excludeпараметра:

--exclude=GLOB
    Skip files whose base name matches GLOB (using wildcard matching).
    A file-name glob can use *, ?, and [...]  as wildcards, and \ to
    quote a wildcard or backslash character literally.

Оболонка, як правило, сама намагатиметься розширити такий візерунок, щоб уникнути цього, слід навести його:

--exclude-dir='dir?'

Ви можете використовувати фігурні фігурні дужки і цитувати виключити візерунки разом так:

--exclude-dir={'dir?','dir??'}

Шаблон може охоплювати кілька сегментів шляху:

--exclude-dir='some*/?lse'

Це виключало б подібний каталог topdir/something/else.


13

Часто користуйтеся цим:

grepможе використовуватися спільно з -r(рекурсивний), i(ігнорувати випадок) та -o(друкує лише сумісну частину рядків). Виключити filesвикористання --excludeта виключити використання каталогів --exclude-dir.

Збираючи його разом, ви закінчуєте щось на кшталт:

grep -rio --exclude={filenames comma separated} \
--exclude-dir={directory names comma separated} <search term> <location>

Описуючи це, це звучить набагато складніше, ніж є насправді. Простіше проілюструвати простим прикладом.

Приклад:

Припустимо, я шукаю поточний проект для всіх місць, де я явно встановлюю значення рядка debuggerпід час сеансу налагодження, і тепер хочу переглянути / видалити.

Я пишу сценарій під назвою findDebugger.shі використовую grepдля пошуку всіх подій. Однак:

Що стосується виключень файлів - я хочу переконатися, що .eslintrcйого ігнорують (це насправді має правило зв’язування, debuggerтому слід виключити). Так само я не хочу, щоб у будь-яких результатах посилався на мій власний сценарій.

Що стосується виключень каталогів - я хочу виключити, node_modulesоскільки він містить багато бібліотек, на які є посилання, debuggerі я не зацікавлений у цих результатах. Крім того, я просто хочу опустити .ideaта .gitприховані каталоги, тому що я не переймаюся тими місцями пошуку та хочу зберегти виконавця пошуку.

Отже, ось результат - я створюю сценарій, який називається findDebugger.sh:

#!/usr/bin/env bash
grep -rio --exclude={.eslintrc,findDebugger.sh} \
--exclude-dir={node_modules,.idea,.git} debugger .

Я вважаю, що варіант "r" повинен бути надрукований з великого регістру "-R".
hornetbzz

1
Цікаво. "r" завжди працював для мене на nix та mac.
Арсельдон

Коли я писав свою відповідь , я використовував -R(не пригадую, чому зараз). Я зазвичай використовую -r. Виявляється, що великі версії слід за символьними посиланнями . TIL.
Johnsyweb

@Johnsyweb - спасибі схвалив вашу відповідь - не пам’ятайте, коли, ймовірно, у 2016 році, коли я додав цю :)
arcseldon

10

Ви можете спробувати щось на кшталт grep -R search . | grep -v '^node_modules/.*'


34
Не таке вдале рішення в деяких випадках. Наприклад: Якщо каталог 'node_modules' є величезним, з великою кількістю помилкових позитивних збігів (звідси необхідність фільтрувати каталог), то перший grep витрачає багато часу на пошук підкаталога, а потім на другу фільтрацію grep. поза сірниками. Швидше виключити node_modules в першому грепі.
ГуруМ

2
Мене не хвилює повільність, я можу подивитися на команду і знати, що вона робить
Funkodebat

1
Дітто для коментаря Гуру. /varКоли /var/runв моєму випадку потрапляє гребінь, висить . Звідси я хочу уникати каталогу в першу чергу.
jww

3
--exclude-dirнайкраще рішення на 2016 рік
Омар Тарік

10

Якщо ви шукаєте код у сховищі git і node_modulesє у своєму .gitignore, ви можете використовувати git grep. git grepздійснює пошук відстежуваних файлів у робочому дереві, ігноруючи все, з чого.gitignore

git grep "STUFF"

Це дуже корисна порада. Дякую.
НКМ

4

Дуже корисно, особливо для тих, хто працює з Node.js, де ми хочемо уникати пошуку всередині "node_modules":

find ./ -not -path "*/node_modules/*" -name "*.js" | xargs grep keyword

2

Проста робоча команда:

root/dspace# grep -r --exclude-dir={log,assetstore} "creativecommons.org"

Вище я проглядаю текст "creativecommons.org" у поточному каталозі "dspace" і виключаю dirs {log, resourcestore}.

Зроблено.


Акуратний, включаючи кілька довідників у дужках
Mijo

2

Тут було дано багато правильних відповідей, але я додаю цю, щоб підкреслити один момент, який спричинив невдалі спроби деяких невдач: exclude-dir бере схему , а не шлях до каталогу.

Скажіть, що ваш пошук:

grep -r myobject

І ви помічаєте, що ваш результат переповнений результатами src/other/objects-folder. Ця команда не буде дасть вам запланованого результату:

grep -r myobject --exclude-dir=src/other/objects-folder

І вам може бути цікаво, чому exclude-dirце не працює! Фактично виключити результати зobjects-folder , просто зробіть це:

grep -r myobject --exclude-dir=objects-folder

Іншими словами, просто використовуйте папки , а не шлях. Очевидно, коли ти це знаєш.

На чоловіковій сторінці:

--exclude-dir = GLOB
Пропустити будь-який каталог командного рядка з суфіксом імені, що відповідає шаблону GLOB. Під час рекурсивного пошуку пропустіть будь-який підкаталог, базове ім'я якого відповідає GLOB. Ігноруйте будь-які зайві косої риски в GLOB.


2

Цей для мене працює:

grep <stuff> -R --exclude-dir=<your_dir>

5
Чим ця відповідь відрізняється від вже опублікованої?
aexl


-1

Більш простим способом було б фільтрувати результати за допомогою "grep -v".

grep -i needle -R * | grep -v node_modules


12
Це фактично та сама відповідь, яку DipSwitch дав 3 роки раніше. У нього є ті самі проблеми.
jww
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.