рекурсивна grep: виключити конкретні каталоги


49

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

grep -Rni "myfunc" .

На великих базах кодів це може бути повільним, тому я використовую --incldue для обмеження / розширення білого списку.

grep -Rni --include=*.java "myfunc" .

Однак було б ефективніше виключити (підрізати) цілі підкаталоги, я думаю:

grep -Rni --exclude=/.svn/ "myfunc" .

Але --exclude підтримує лише шаблони файлів, такі як * .java вище. Як я можу виключити каталоги?

Відповіді:


10

Ви можете заглянути в аке .

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


Ack виглядає досить добре. приємно, що він інтуїтивно виключає непотрібні файли. опція --nogroup дає схожий результат на grep -Rni
gabor

2
Ак трохи повільний. Ви можете спробувати The Silver Searcher (Ag) або ripgrep (rg).
користувач31389

62
grep -r --exclude-dir=dev --exclude-dir=sys --exclude-dir=proc PATTERN data

Джерело: https://stackoverflow.com/questions/2799246/grep-excluding-a-specific-folder-using


17
Зауважте, що це рекурсивно виключає. ./devбуде виключено НАД ЗІ ./foo/bar/dev. Використовуйте --exclude-dir=./devлише для першого випадку.
Cory Walker

4
Ви також можете трохи скоротити це за допомогою глобалізації: bash grep -r --exclude-dir={dev,sys,proc} PATTERN data Єдина проблема з глобінгом полягає в тому, що я не можу змусити його працювати в моєму ударі. У такому випадку я повинен тримати їх окремо.
b01

3
Також зауважив, що {} працює лише у тому випадку, якщо ви розмістили більше 1 запису, це означає --exclude-dir = {home, .svn} - це працює, але --exclude-dir = {. Svn} не працює. Даремно витрачаю час, щоб зрозуміти, чому {} не працює, тому що я тестую з 1 записом в першу чергу.
林果 皞

Якщо ви використовуєте {}один запис, вам, мабуть, потрібна одинарна кома, щоб зробити це масивом (не впевнений, як Bash обробляє це). Замість цього я зробив псевдонім у своїх .bash_aliases, який перетворюється на список папок, які я завжди хочу виключити, наприклад .git, .svn, .hg, .cache, а потім додаю їх через цикл із --exclude-dir $dirа потім розгорніть цей масив у псевдонімі grep.
dragon788

6

ви можете використовувати натомість:

find . -not -path "*/.svn*" -not -type d -exec grep -ni "myfunc" {} \; -print

Гаразд, так що це трохи назад, ви отримуєте результати грепу спочатку, а потім шлях. Може хтось інший має кращу відповідь?


3
добре, мені це дуже подобається. Звичайно, пошук набагато гнучкіший. Єдина відмінність між результатами полягає в тому, що "grep -Rni" надрукує ім'я файлу для кожної відповідності, тоді як "find -exec grep" надрукує ім'я файлу в одному рядку, а потім по одному рядку для кожного матчу (з номером рядка та вмістом рядка ). Використання "grep -Hni" змушує назву файлу відображатись у кожному рядку
gabor

Дякую за надання єдиної відповіді, яка працювала для систем, які мають цю корочку, без grep - exclude-dir, але все одно над цим потрібно працювати
Дмитро БД,

2

Ось повний приклад зі сценарію в одному з моїх проектів, який може допомогти, я називаю цей файл "all_source" (позначений як виконуваний файл) і вкладаю його в кореневий редактор мого проекту, а потім називаю його, як grep myfunc $(./all_source)сортування в кінці сценарію. необов’язково.

#!/bin/bash

find . \
    -type d \( \
            -wholename './lib' -o \
            -wholename './vc6' -o \
            -name 'gen' -o \
            -name '.svn' \
            \) -prune -o \
    -type f \( \
            -name '*.h' -o \
            -name '*.cpp' -o \
            -name '*.c' -o \
            -name '*.lua' -o \
            -name '*.*awk' \) -print \
    | sort

Цей скрипт повертає всі імена файлів у проекті, які відповідають *.h, *.cpp, *.c, *.lua, *.*awk, але не здійснює пошук у всіх папках з назвою .svn та gen папок, а також пропусканні папок для ./libта ./vc6(але лише тих, що знаходяться з кореня проекту). Тож коли ви grep myfunc $(./all_source)це робите, у цих файлах є лише зображення. Вам також потрібно буде зателефонувати це з кореневого режиму проекту.


0

Існує також опція -prune для пошуку:

 find . -path "*/.svn*" -prune -o -not -type d -exec grep -ni "myfunc" {} \; -print

0

Ви можете спробувати зробити це:

grep -R  "myfunc" . | grep -v path_to_exclude/

Наприклад: Якщо ви не хочете шукати вміст у файлах журналу, просто виконайте наступне:

grep -R "myfunc" . | grep -v log/
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.