grep -rn --exclude-dir={.git,node_modules,vendor} 'TODO' . находит все совпадения, пропуская три каталога, которые портят почти любой рекурсивный grep в реальном репозитории. --exclude-dir работает только вместе с -r и сравнивает голое имя каталога, а не путь. Дальше — весь рецепт: от наивного рекурсивного поиска до момента, когда проще поставить ripgrep.
1. Искать по всему проекту
$ clai найди TODO во всех файлах внутри g→ grep -rn 'TODO' g/g/src/a.js:1:TODO fixg/node_modules/b.js:1:TODO dep
-r рекурсивно, -n добавляет номер строки. Проблема видна сразу: половина находок из чужого кода.
2. Исключить один каталог
$ clai найди TODO, но не заглядывай в node_modules→ grep -rn --exclude-dir=node_modules 'TODO' g/g/src/a.js:1:TODO fix
--exclude-dir работает только вместе с -r. Имя каталога указывается без слешей — это шаблон имени, а не путь.
3. Исключить сразу несколько
$ clai найди TODO, пропусти node_modules, .git и vendor→ grep -rn --exclude-dir={.git,node_modules,vendor} 'TODO' .
Фигурные скобки разворачивает оболочка ещё до запуска grep — он получит три отдельных флага. В sh без поддержки brace expansion придётся писать три --exclude-dir подряд.
4. Искать только в нужных файлах
$ clai найди TODO только в javascript-файлах→ grep -rn --include='*.js' 'TODO' .
--include это белый список. Когда вы знаете, где искать, он и короче, и быстрее длинной цепочки исключений.
5. Не спотыкаться о бинарники
$ clai найди TODO, игнорируя бинарные файлы→ grep -rnI 'TODO' .
Без -I grep на бинарном файле печатает «Binary file … matches» вместо строки — это засоряет вывод и ломает разбор результата скриптом. -I просто пропускает такие файлы.
6. Когда флагов становится слишком много
$ clai найди TODO в проекте, уважая gitignore→ rg 'TODO'
ripgrep по умолчанию читает .gitignore, пропускает .git и бинарники — то есть делает всё вышеперечисленное без единого флага, и быстрее. Если вы третий раз за день пишете длинную цепочку --exclude-dir, пора его поставить.
Грабли
--exclude-dirбез-rмолча ничего не делает. Флаг принимается, но не применяется, и вы решите, что он не работает.- Шаблон в
--exclude-dirне путь.--exclude-dir=src/vendorне сработает, потому что сравнивается имя каталога, а не путь до него. Пишите--exclude-dir=vendor. - Кавычки вокруг шаблона обязательны.
grep -r --include=*.jsоболочка развернёт по файлам текущего каталога до запуска grep, и вы получите совсем не тот поиск.
Похожие вопросы
Как исключить сам каталог .git? --exclude-dir=.git. Точка в начале имени ничего не меняет, а вот -r по репозиторию без этого флага выдаёт мусор из объектов git.
Как посчитать совпадения, а не показать их? grep -rc 'TODO' . печатает счётчик по каждому файлу, grep -rho 'TODO' . | wc -l — общее число вхождений.
grep или ripgrep? grep есть везде и его надо знать. ripgrep быстрее и по умолчанию делает разумные вещи, но его надо ставить, а на чужом сервере это не всегда возможно.
Читайте также
- Найти и заменить во всех файлах проекта
- Вывести колонку из CSV с помощью awk
- JSON в командной строке
Не запоминайте флаги исключений — опишите, что ищете, а grep напишет CliAI. Установка одной строкой.