rekursywny grep: wyklucz określone katalogi

49

Używam rekurencyjnego grep do znajdowania plików źródłowych o określonej zawartości.

grep -Rni "myfunc" .

W przypadku dużych baz kodu może to być wolne, więc używam --incldue do ograniczenia / dodawania do białej listy.

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

Wydaje mi się jednak, że skuteczniej byłoby wykluczyć (przyciąć) całe podkatalogi:

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

Ale opcja --exclude obsługuje tylko wzorce plików, takie jak * .java powyżej. Jak mogę wykluczyć katalogi?

gabor
źródło

Odpowiedzi:

10

Możesz zajrzeć do potwierdzenia .

Właśnie zacząłem go używać, ale wydaje się, że nadaje się do tego.

Alex Feinman
źródło
ack wygląda całkiem nieźle. Fajnie, że intuicyjnie wyklucza niechciane pliki. opcja --nogroup daje podobny wynik jak grep -Rni
gabor
2
Ack jest trochę powolny. Możesz wypróbować The Silver Searcher (Ag) lub ripgrep (rg).
user31389,
62
grep -r --exclude-dir=dev --exclude-dir=sys --exclude-dir=proc PATTERN data

Źródło: https://stackoverflow.com/questions/2799246/grep-exclusion-a-specific-folder-using

Henrik
źródło
17
Zauważ, że rekurencyjnie to wyklucza. ./devzostaną wykluczone W POŁĄCZENIU ./foo/bar/dev. Użyj, --exclude-dir=./devaby zastosować tylko w pierwszym przypadku.
Cory Walker
4
Możesz także trochę to skrócić poprzez globbing: bash grep -r --exclude-dir={dev,sys,proc} PATTERN data Jedynym problemem z globbingiem jest to, że nie mogę zmusić go do działania w moim bashu. W takim przypadku muszę je rozdzielić.
b01,
3
Zauważył również, że {} działa tylko, jeśli wstawisz więcej niż 1 wpisy, co oznacza, że ​​--exclude-dir = {home, .svn} działa, ale --exclude-dir = {. Svn} nie działa. Marnuję czas, aby dowiedzieć się, dlaczego {} nie działa, ponieważ najpierw testuję 1 wpis.
Jeśli używasz {}pojedynczego wpisu, prawdopodobnie potrzebujesz jednoargumentowego przecinka, aby uczynić go tablicą (nie jestem pewien, jak Bash sobie z tym radzi). Zamiast tego stworzyłem alias w moim .bash_aliases, który zapętla się nad listą folderów, które zwykle zawsze chcę wykluczyć, np. .Git, .svn, .hg, .cache, a następnie dodaję je za pomocą pętli z --exclude-dir $dira następnie rozwiń tę tablicę do aliasu grep.
dragon788
6

zamiast tego możesz użyć find:

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

OK, więc to trochę wstecz, najpierw otrzymujesz wyniki grep, a potem ścieżkę. Może ktoś inny ma lepszą odpowiedź?

Josh
źródło
3
ok, bardzo to lubię. oczywiście find jest o wiele bardziej elastyczny. jedyną różnicą między danymi wyjściowymi jest to, że „grep -Rni” wypisze nazwę pliku dla każdego dopasowania, podczas gdy „find -exec grep” wydrukuje nazwę pliku w jednym wierszu, a następnie w jednym wierszu dla każdego dopasowania (z numerem i zawartością wiersza ). użycie „grep -Hni” wymusza wyświetlenie nazwy pliku w każdym wierszu
gabor
Dziękujemy za udzielenie jedynej odpowiedzi, która zadziałała dla systemów, które są tak chrupiące, bez grep - excclude-dir, ale nadal trzeba nad tym pracować
Dmitri DB
2

Oto pełny przykład skryptu z jednego z moich projektów, który może pomóc, nazywam ten plik „all_source” (oznaczony jako wykonywalny) i umieszczam go w katalogu głównym mojego projektu, a następnie nazywam go tak, jakby grep myfunc $(./all_source)sortowanie na końcu skryptu było całkowicie opcjonalny.

#!/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

Ten skrypt zwraca wszystkie nazwy plików w projekcie, które pasują *.h, *.cpp, *.c, *.lua, *.*awk, ale nie wyszukuje we wszystkich folderach o nazwach .svn i foldery gen, a także pomija foldery ./libi ./vc6(ale tylko te bezpośrednio z katalogu głównego projektu). Więc kiedy to zrobisz grep myfunc $(./all_source), tylko greps w tych plikach. Musisz to również wywołać z katalogu głównego projektu.

Mike Nelson
źródło
0

Istnieje również opcja -prune, aby znaleźć:

 find . -path "*/.svn*" -prune -o -not -type d -exec grep -ni "myfunc" {} \; -print
misiu_mp
źródło
0

Możesz spróbować to zrobić:

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

Np .: Jeśli nie chcesz przeszukiwać zawartości plików dziennika, wykonaj następujące czynności:

grep -R "myfunc" . | grep -v log/
Akshatha
źródło