Jak mogę wykluczyć katalogi z grep -R?

668

Chcę przeglądać wszystkie podkatalogi, z wyjątkiem katalogu „node_modules”.

TIMEX
źródło
3
Zobacz superuser.com/q/66715/59933
boricious
14
Po prostu wpisz „man grep”, a zobaczysz opcje --exclude i --exclude-dir wymienione tutaj - z nagłówka tego pytania,
zakładam
34
Jeśli szukasz kodu w repozytorium git i node_modulesjest w twoim .gitignore, git grep "STUFF"jest to najłatwiejszy sposób. git grepprzeszukuje śledzone pliki w działającym drzewie, ignorując wszystko od.gitignore
0xcaff
2
Przykład dla węzła: grep -R --exclude-dir={node_modules,bower_components} "MyString" | cut -c1-"$COLUMNS"- ponadto możesz zawsze aliasować to w powłoce na „nodegrep” lub cokolwiek i użyć argumentu polecenia jako ciągu wejściowego.
bshea

Odpowiedzi:

394

ROZWIĄZANIE 1 (połącz findi grep)

Celem tego rozwiązania nie jest poradzenie sobie z grepwydajnością, ale pokazanie rozwiązania przenośnego: powinno również działać z busybox lub wersją GNU starszą niż 2.5.

Użyj find, aby wykluczyć katalogi foo i bar:

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

Następnie połącz findi nierekurencyjne użycie grepjako rozwiązania przenośnego:

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

ROZWIĄZANIE 2 (rekurencyjne użycie grep):

Znasz już to rozwiązanie, ale dodaję je, ponieważ jest to najnowsze i wydajne rozwiązanie. Uwaga: jest to mniej przenośne rozwiązanie, ale bardziej czytelne dla człowieka.

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

Aby wykluczyć wiele katalogów, użyj --exclude-dirjako:

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

ROZWIĄZANIE 3 (Ag)

Jeśli często przeszukujesz kod, Ag (The Silver Searcher) jest znacznie szybszą alternatywą dla grep, dostosowaną do wyszukiwania kodu. Na przykład automatycznie ignoruje pliki i katalogi wymienione w .gitignore, więc nie musisz ciągle przekazywać tych samych uciążliwych opcji wykluczania do greplub find.

hornetbzz
źródło
2
ta kombinacja wyszukuje szybciej niż --exclude-dir=diri pokazuje wyniki z kolorami - łatwa do odczytania
Maxim Yefremov
27
„ta kombinacja” find ... -execnie jest szybsza niż grep --exclude-dirdla mnie. Ogromną zaletą do grep (około pięć razy szybciej z 26k + plików, odfiltrowane od 38 tys + na HDD), chyba wymienić \;z +za find / exec kombi. Wtedy grep jest „tylko” o około 30% szybszy. Składnia grep jest również czytelna dla człowieka :).
Kjell Andreassen
Zgoda, ponieważ jest to oczywiste. Niektóre busyboxy nie mają polecenia GREP.
hornetbzz
10
zauważając również, że można wykluczyć wielokrotność za pomocą--exclude-dir={dir1,dir2}
suh
4
Nie jestem wcale zaskoczony, że node_modulesjest to kanoniczny przykład.
pdoherty926
982

Najnowsze wersje GNU Grep (> = 2.5.2 ) zapewniają:

--exclude-dir=dir

co wyklucza katalogi pasujące do wzorca dirz rekurencyjnych wyszukiwań katalogów.

Możesz więc zrobić:

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

Aby uzyskać więcej informacji na temat składni i użycia, zobacz

W przypadku starszych GNU Greps i POSIX Grep używaj, findjak sugerowano w innych odpowiedziach.

Lub po prostu użyj ack( Edycja : lub Srebrny Poszukiwacz ) i gotowe!

Johnsyweb
źródło
4
@Manocho: Jeśli uważasz, że ackjest świetny, wypróbuj The Silver Searcher i zobacz wzrost prędkości!
Johnsyweb
30
Składnia dla niecierpliwych: --exclude-dir=dirużywa grepwzorców wyrażeń regularnych, a nie globowania plików powłoki. Wzory działają na ścieżkach względem bieżącego katalogu. Więc użyć wzoru --exclude-dir=dir, nie --exclude-dir="/root/dir/*".
tanius
15
Jeśli chcesz wykluczyć z wyszukiwania wiele katalogów, czy jest lepsza opcja niż użycie $ grep -r --exclude-dir=dir1 --exclude-dir=dir2 "string" /path/to/search/dir:?
Darszan Chaudhary
4
Prawdopodobnie spędziłem na tym zbyt dużo czasu niż jakikolwiek rozsądny człowiek, ale nie mogę przez całe życie wymyślić, jak wykluczyć podkatalog z wyszukiwania - grep -r --exclude-dir=public keyword .działa, ale grep -r --exclude-dir='public/dist' keyword .nie działa. Próbowałem dodać symbole zastępcze, znaki ucieczki itp., Ale nic nie pomaga.
dkobozev
72
Wyklucz wiele takich katalogów:grep -r "Request" . --exclude-dir={node_modules,git,build}
maverick97
77

Jeśli chcesz wykluczyć wiele katalogów :

„r” dla rekurencyjnego, „l”, aby wydrukować tylko nazwy plików zawierających dopasowania, a „i”, aby zignorować rozróżnienie wielkości liter:

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

Przykład: Chcę znaleźć pliki zawierające słowo „cześć”. Chcę wyszukiwać we wszystkich moich katalogach linux oprócz katalogu proc, katalogu rozruchowego, katalogu sys i katalogu głównego :

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

Uwaga: powyższy przykład musi być rootem

Uwaga 2 (zgodnie z @skplunkerin): nie dodawaj spacji po przecinkach {dir1,dir2,dir3}

Azodium
źródło
5
UWAGA: nie dodawaj spacji po przecinkach w{dir1,dir2,dir3}
skplunkerin
Dzięki, przydatne, gdy grep'ing przez obszar roboczy SVN:grep -Irsn --exclude-dir=.svn 'foo' .
RAM237
1
Możesz po prostu podać tę --exclude-diropcję wiele razy.
Walf
44

Ta składnia

--exclude-dir={dir1,dir2}

jest rozszerzany przez powłokę (np. Bash), a nie przez grep, do tego:

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

Cytowanie uniemożliwi rozwinięcie go przez powłokę, więc to nie zadziała:

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

Wzory używane z --exclude-dirsą tego samego rodzaju wzorcami opisanymi na stronie podręcznika dla --excludeopcji:

--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.

Powłoka zazwyczaj będzie próbowała rozwinąć taki wzór, więc aby tego uniknąć, powinieneś go zacytować:

--exclude-dir='dir?'

Możesz używać nawiasów klamrowych i cytowanych razem wykluczać wzory w następujący sposób:

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

Wzór może obejmować wiele segmentów ścieżki:

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

Wykluczałoby to katalog podobny do topdir/something/else.

Derek Veit
źródło
13

Często używaj tego:

grepmoże być używany w połączeniu z -r(rekurencyjne), i(ignoruj ​​wielkość liter) i -o(drukuje tylko pasującą część linii). Aby wykluczyć filesużycie --excludei aby wykluczyć użycie katalogów --exclude-dir.

Podsumowując, otrzymujesz coś takiego:

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

Jego opis sprawia, że ​​brzmi o wiele bardziej skomplikowane niż jest w rzeczywistości. Łatwiej to zilustrować prostym przykładem.

Przykład:

Załóżmy, że szukam bieżącego projektu dla wszystkich miejsc, w których jawnie ustawiam wartość debuggerciągu podczas sesji debugowania, a teraz chcę przejrzeć / usunąć.

Piszę skrypt o nazwie findDebugger.shi używam grepdo znalezienia wszystkich wystąpień. Jednak:

W przypadku wykluczeń plików - chciałbym się upewnić, że .eslintrczostanie zignorowany (w rzeczywistości jest to reguła podszywania się, debuggerdlatego należy go wykluczyć). Podobnie nie chcę, aby mój skrypt zawierał odwołania w jakichkolwiek wynikach.

Wyłączenia katalogów - chcę wykluczyć, node_modulesponieważ zawiera wiele bibliotek, które zawierają odwołania debuggeri nie jestem zainteresowany tymi wynikami. Chciałbym też pominąć .ideai .gitukryć katalogi, ponieważ nie dbam też o te lokalizacje wyszukiwania i chcę zachować skuteczność wyszukiwania.

Oto wynik - tworzę skrypt o nazwie findDebugger.sh:

#!/usr/bin/env bash
grep -rio --exclude={.eslintrc,findDebugger.sh} \
--exclude-dir={node_modules,.idea,.git} debugger .
arcseldon
źródło
Uważam, że opcja „r” powinna być wydrukowana z dużą literą „-R”.
hornetbzz 12.03.18
1
Ciekawy. „r” zawsze działało dla mnie na nix i mac.
arcseldon
Kiedy napisałem odpowiedź , użyłem -R(nie pamiętam, dlaczego teraz). Zwykle używam -r. Okazuje się, że wielka wersja podąża za dowiązaniami symbolicznymi . TIL
Johnsyweb
@Johnsyweb - dzięki. przegłosował twoją odpowiedź - nie przypominaj sobie kiedy, prawdopodobnie w 2016 roku, kiedy to dodałem :)
arcseldon
10

Możesz spróbować czegoś takiego grep -R search . | grep -v '^node_modules/.*'

Przełącznik DIP
źródło
34
W niektórych przypadkach niezbyt dobre rozwiązanie. Na przykład: Jeśli katalog „node_modules” jest ogromny i zawiera wiele fałszywie pozytywnych dopasowań (stąd potrzeba odfiltrowania katalogu), to pierwszy grep marnuje dużo czasu na przeszukiwanie podkatalogu, a NASTĘPNIE drugi filtr grep mecze. Szybciej jest wykluczyć node_modules w pierwszym grep.
GuruM,
2
nie dbam o powolność, mogę spojrzeć na komendę i wiedzieć, co robi
Funkodebat
1
To samo dotyczy komentarza Guru. Grep /varzawiesza się, gdy uderza /var/runw moim przypadku. Dlatego przede wszystkim chcę uniknąć katalogu.
jww
3
--exclude-dirjest najlepszym rozwiązaniem od 2016 r.
Omar Tariq,
10

Jeśli szukasz kodu w repozytorium git i node_modulesjest w twoim .gitignore, możesz użyć git grep. git grepprzeszukuje śledzone pliki w działającym drzewie, ignorując wszystko od.gitignore

git grep "STUFF"
0xcaff
źródło
To bardzo przydatna wskazówka. Dzięki.
NKM
4

Bardzo przydatne, szczególnie dla osób zajmujących się Node.js, w których chcemy uniknąć przeszukiwania „node_modules”:

find ./ -not -path "*/node_modules/*" -name "*.js" | xargs grep keyword
Nestor Urquiza
źródło
2

Proste działające polecenie:

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

Powyżej szukam tekstu „creativecommons.org” w bieżącym katalogu „dspace” i wykluczam katalogi {log, assetstore}.

Gotowy.

Łajno
źródło
Zgrabne, w tym kilka katalogów w nawiasach
Mijo,
2

Podano tu wiele poprawnych odpowiedzi, ale dodaję tę, aby podkreślić jeden punkt, który spowodował, że niektóre pośpieszne próby zawiodły wcześniej: exclude-dirprzyjmuje wzorzec , a nie ścieżkę do katalogu.

Powiedz, że twoje wyszukiwanie to:

grep -r myobject

Zauważysz, że wyniki są zaśmiecone wynikami z src/other/objects-folder. To polecenie nie da zamierzonego wyniku:

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

I możesz się zastanawiać, dlaczego exclude-dirnie działa! Aby faktycznie wykluczyć wyniki z objects-folder, po prostu zrób to:

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

Innymi słowy, po prostu użyj nazwy folderu , a nie ścieżki. Oczywiste, kiedy już to wiesz.

Ze strony podręcznika:

--exclude-dir = GLOB
Pomiń dowolny katalog wiersza poleceń z sufiksem nazwy zgodnym ze wzorcem GLOB. Podczas wyszukiwania rekurencyjnego pomiń dowolny podkatalog, którego podstawowa nazwa pasuje do GLOB. Zignoruj ​​zbędne ukośniki końcowe w GLOB.

Nagev
źródło
2

Ten działa dla mnie:

grep <stuff> -R --exclude-dir=<your_dir>
angelo.mastro
źródło
5
Czym różni się ta odpowiedź od już opublikowanej?
aexl
1
find . ! -name "node_modules" -type d 
Jacek
źródło
-1

Prostszym sposobem byłoby filtrowanie wyników za pomocą „grep -v”.

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

Morris
źródło
12
To jest właściwie ta sama odpowiedź, którą DipSwitch podał 3 lata wcześniej. Ma te same problemy.
jww