Jak znaleźć wszystkie pliki zawierające określony tekst w systemie Linux?

5254

Próbuję znaleźć sposób na przeskanowanie całego systemu Linux w poszukiwaniu wszystkich plików zawierających określony ciąg tekstu. Dla wyjaśnienia szukam tekstu w pliku, a nie w nazwie pliku.

Kiedy szukałem, jak to zrobić, dwukrotnie natknąłem się na to rozwiązanie:

find / -type f -exec grep -H 'text-to-find-here' {} \;

Jednak to nie działa. Wygląda na to, że wyświetla każdy pojedynczy plik w systemie.

Czy to blisko właściwego sposobu na zrobienie tego? Jeśli nie, jak powinienem? Ta możliwość znajdowania ciągów tekstowych w plikach byłaby niezwykle przydatna w przypadku niektórych projektów programistycznych, które wykonuję.

Nathan
źródło
21
pamiętaj, że grep zinterpretuje dowolną .między innymi jako jednoznaczny znak wieloznaczny. Radzę zawsze używać fgrep lub egrep.
Walter Tross
10
w każdym razie byłeś prawie na miejscu! Wystarczy wymienić -Hz -l(a może grepz fgrep). Aby wykluczyć pliki o określonych wzorcach nazw, których użyłbyś findw bardziej zaawansowany sposób. Warto jednak nauczyć się obsługiwać find. Właśnie man find.
Walter Tross,
6
find … -exec <cmd> +jest łatwiejszy do pisania i szybszy niż find … -exec <cmd> \;. Działa tylko wtedy, gdy <cmd>akceptuje dowolną liczbę argumentów nazwy pliku. Oszczędność czasu wykonania jest szczególnie duża, jeśli <cmd>uruchamia się powoli, jak skrypty Python lub Ruby.
hagello
Aby wyszukiwać nierekurencyjnie w podanej ścieżce, polecenie brzmi `grep --include = *. Txt -snw" wzorzec "ścieżka / *.
Stéphane Laurent,
@ StéphaneLaurent Myślę, że komplikujesz to za bardzo. Po prostu powiedzgrep "pattern" path/*.txt
fedorqui „SO przestań szkodzić”

Odpowiedzi:

9508

Wykonaj następujące czynności:

grep -rnw '/path/to/somewhere/' -e 'pattern'
  • -rlub -Rjest rekurencyjny,
  • -n jest numerem wiersza i
  • -w oznacza dopasowanie całego słowa.
  • -l (małe litery L) można dodać, aby podać nazwę pasujących plików.

Wraz z tymi, --exclude, --include, --exclude-dirflagi mogą być wykorzystane do efektywnego poszukiwania:

  • Przeszukuje tylko te pliki, które mają rozszerzenia .c lub .h:

    grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"
    
  • Wyklucza to wyszukiwanie wszystkich plików z rozszerzeniem .o:

    grep --exclude=*.o -rnw '/path/to/somewhere/' -e "pattern"
    
  • W przypadku katalogów można wykluczyć określony katalog (y) za pomocą --exclude-dirparametru. Na przykład wyklucza to katalog dir1 /, dir2 / i wszystkie pasujące do * .dst /:

    grep --exclude-dir={dir1,dir2,*.dst} -rnw '/path/to/somewhere/' -e "pattern"
    

Działa to dla mnie bardzo dobrze, aby osiągnąć prawie taki sam cel jak twój.

Aby uzyskać więcej opcji, sprawdź man grep.

rakib_
źródło
74
użyj --exclude. jak "grep -rnw --exclude = *. o 'wzorzec katalogu' -e"
rakib_
98
warto zauważyć: wydaje się, że ropcja jest leniwa (najpierw przechodzi w głąb głębi, potem zatrzymuje się po pierwszym katalogu), podczas gdy Rjest zachłanna (poprawnie przejdzie całe drzewo).
Eliran Malka
5
grep -rnw „Ciąg, którego szukałem” zrobił to, czego potrzebowałem. Dzięki!
ViliusK,
33
Uwaga (szczególnie dla początkujących): Znaki cudzysłowu w powyższym poleceniu są ważne.
madD7,
69
@Eliran Malka Rpl rbędzie poprawnie przechodził przez katalogi, ale Rbędzie podążał za dowiązaniami symbolicznymi.
bzeaman
1496

Możesz użyć grep -ilR:

grep -Ril "text-to-find-here" /
  • i oznacza ignoruj ​​wielkość liter (opcjonalnie w twoim przypadku).
  • R oznacza rekurencyjny.
  • l oznacza „pokaż nazwę pliku, a nie sam wynik”.
  • / oznacza rozpoczęcie od katalogu głównego komputera.
fedorqui „SO przestań szkodzić”
źródło
85
Z mojego doświadczenia -iwynika , że powoduje to spowolnienie, więc nie używaj go, jeśli nie jest to konieczne. Przetestuj to w określonym katalogu, a następnie uogólnij. Należy go ukończyć w ciągu kilku minut. Myślę, że wyrażenie regularne spowolniłoby to. Ale moje komentarze opierają się na przypuszczeniach, sugeruję przetestowanie go timeprzed linią.
fedorqui „SO przestań krzywdzić”
4
Tak, /*oznacza to. W każdym razie właśnie go przetestowałem i zauważyłem, że to po prostu /działa.
fedorqui „SO przestań szkodzić”
10
Jeśli nie używasz wyrażenia regularnego, możesz użyć fgrep zamiast grep w większości systemów.
markle976,
8
Tak @ markle976, w rzeczywistości od człowieka grep: fgrep is the same as grep -F -> Interpret PATTERN as a list of fixed strings.
fedorqui „SO przestań szkodzić”
17
Możesz zastąpić / ścieżką do katalogu grep -Ril "text-to-find-here" ~/sites/lub użyć. dla bieżącego katalogugrep -Ril "text-to-find-here" .
Czarny
329

Możesz użyć ack . To jest jak grep dla kodu źródłowego. Za jego pomocą możesz przeskanować cały system plików.

Po prostu zrób:

ack 'text-to-find-here'

W twoim katalogu głównym.

Możesz także użyć wyrażeń regularnych , określić typ pliku itp.


AKTUALIZACJA

Właśnie odkryłem Srebrnego Poszukiwacza , który jest podobny do potwierdzenia, ale 3-5 razy szybszy od niego, a nawet ignoruje wzorce z .gitignorepliku.

Stephan
źródło
57
Bardzo przydatne, proste i szybkie. Ostrzeżenie: „W dystrybucjach wywodzących się z Debiana, ack jest pakowane jako„ ack-grep ”, ponieważ„ ack ”już istniał” ( fromyondgrep.com/install ). Możesz skończyć z uruchomieniem konwertera kodu Kanji na tych Linuksach ...
Jose_GD
11
ack lub ack-grep mają ładne pasemka, ale znajdź + grep, gdy odpowiednie użycie jest znacznie lepsze w działaniu
Sławomir Lenart
14
Zauważ, że ripgrep jest szybszy niż cokolwiek innego tutaj wspomnianego, w tym Srebrny Poszukiwacz i zwykły 'gre grep. Zobacz ten post na blogu jako dowód.
Radon Rosborough
194

Możesz użyć:

grep -r "string to be searched"  /path/to/dir

rOznacza rekurencyjne i tak będzie szukać w podanej ścieżce, a także jego podkatalogów. To powie ci nazwę pliku, a także wydrukuje wiersz w pliku, w którym pojawia się ciąg.

Lub polecenie podobne do tego, którego próbujesz (przykład:) do wyszukiwania we wszystkich plikach javascript (* .js):

find . -name '*.js' -exec grep -i 'string to search for' {} \; -print

Spowoduje to wydrukowanie wierszy w plikach, w których pojawia się tekst, ale nie wydrukuje nazwy pliku.

Oprócz tego polecenia możemy również napisać: grep -rn "Ciąg do przeszukania" / ścieżka / do / katalogu / lub / file -r: wyszukiwanie rekurencyjne n: numer wiersza zostanie wyświetlony dla dopasowań

uczeń_19
źródło
1
Dzięki za wersję Find. Moja wersja grep (busybox dla NAS) nie ma opcji -r, naprawdę potrzebowałam innego rozwiązania!
jc
3
Dziękujemy za wersję „znajdź”! Bardzo ważne jest, aby móc filtrować według „ .js” lub „ .txt” itp. Nikt nie chce spędzać godzin, czekając, aż grep zakończy wyszukiwanie wszystkich filmów o gigabajtach z ostatnich rodzinnych wakacji, nawet jeśli polecenie to łatwiejsze do pisania.
mightypile
lepsza wersja grep niż zaakceptowana, ponieważ zaakceptowana nie wyszukuje pół słów
waza123
114

Możesz użyć tego:

grep -inr "Text" folder/to/be/searched/
AR
źródło
12
najłatwiejszy, pełny, rekurencyjny i bez rozróżniania wielkości liter. kciuki w górę.
Francesco Casula
jeśli dodasz -A3 jest jeszcze lepszy
albanx
73

Lista nazw plików zawierających dany tekst

Po pierwsze, uważam, że użyłeś -Hzamiast -l. Możesz także spróbować dodać tekst w cudzysłowie, a następnie {} \.

find / -type f -exec grep -l "text-to-find-here" {} \; 

Przykład

Załóżmy, że szukasz plików zawierających określony tekst „Licencja Apache” w swoim katalogu. Wyświetli wyniki nieco podobne do poniższych (wyniki będą różne w zależności od zawartości katalogu).

bash-4.1$ find . -type f -exec grep -l "Apache License" {} \; 
./net/java/jvnet-parent/5/jvnet-parent-5.pom
./commons-cli/commons-cli/1.3.1/commons-cli-1.3.1.pom
./io/swagger/swagger-project/1.5.10/swagger-project-1.5.10.pom
./io/netty/netty-transport/4.1.7.Final/netty-transport-4.1.7.Final.pom
./commons-codec/commons-codec/1.9/commons-codec-1.9.pom
./commons-io/commons-io/2.4/commons-io-2.4.pom
bash-4.1$ 

Usuń wrażliwość na wielkość liter

Nawet jeśli nie podoba Ci się przypadek taki jak „tekst” a „TEKST”, możesz użyć -iprzełącznika, aby zignorować wielkość liter. Możesz przeczytać dalsze szczegóły tutaj .

Mam nadzieję, że to ci pomoże.

lkamal
źródło
2
To, co robi to polecenie: findprzekaże wszystkie znalezione ścieżki do polecenia grep -l "text-to-find-here" <file found>". Możesz dodać ograniczenia do nazwy pliku, np. find / -iname "*.txt"Aby wyszukiwać tylko w plikach, których nazwa kończy się na.txt
Mene
1
@ Pomocniczy - zawiera przykładowe wyjście, aby uniknąć nieporozumień dla czytelników.
lkamal
2
@Mene To naprawdę smutny stan, że komentarz pomocniczy ma więcej głosów niż twój ... nawet jeśli ich komentarz pochodzi z 2014 roku, a twój jest rok 2017, że ich komentarz ma 6, kiedy powinien mieć dokładnie 0, a twój miał tylko jeden (teraz dwa) to coś, w co chciałbym wierzyć.
Pryftan
@Mene To powiedziawszy, -inamenie rozróżnia wielkości liter, co oznacza, że ​​znajdzie również pliki .TXT, na przykład, a także TxT i TXt i tak dalej.
Pryftan
66

grep( GNU lub BSD )

Możesz użyć grepnarzędzia do rekurencyjnego przeszukiwania bieżącego folderu, takiego jak:

grep -r "class foo" .

Uwaga: -r- Rekurencyjnie przeszukuj podkatalogi.

Możesz także użyć składni globowania do wyszukiwania w określonych plikach, takich jak:

grep "class foo" **/*.c

Uwaga: Korzystając z opcji globbing ( **), skanuje rekursywnie wszystkie pliki z określonym rozszerzeniem lub wzorem. Aby włączyć tę składnię, uruchom: shopt -s globstar. Możesz także użyć **/*.*do wszystkich plików (z wyjątkiem ukrytych i bez rozszerzenia) lub dowolnego innego wzoru.

Jeśli masz błąd, że Twój argument jest za długi, rozważ zawężenie wyszukiwania lub użyj findskładni, na przykład:

find . -name "*.php" -execdir grep -nH --color=auto foo {} ';'

Alternatywnie użyj ripgrep.

ripgrep

Jeśli pracujesz nad większymi projektami lub dużymi plikami, powinieneś użyć ripgrep, takich jak:

rg "class foo" .

Zapoznaj się z dokumentacją, krokami instalacji lub kodem źródłowym na stronie projektu GitHub .

To znacznie szybciej niż jakiekolwiek inne narzędzia jak GNU / BSD grep , ucg, ag, sift, ack, ptlub podobny, ponieważ jest zbudowany na szczycie regex silnika Rust , który używa automatów skończonych, SIMD i agresywny dosłownych optymalizacje aby szukają bardzo szybko.

Obsługuje wzorce ignorowania określone w .gitignoreplikach, więc pojedynczą ścieżkę pliku można dopasować do wielu wzorców globu jednocześnie.


Możesz użyć wspólnych parametrów, takich jak:

  • -i - Niewrażliwe wyszukiwanie.
  • -I - Zignoruj ​​pliki binarne.
  • -w - Wyszukaj całe słowa (w przeciwieństwie do częściowego dopasowywania słów).
  • -n - Pokaż linię swojego meczu.
  • -C/ --context(np. -C5) - Zwiększa kontekst, dzięki czemu widzisz otaczający kod.
  • --color=auto - Zaznacz pasujący tekst.
  • -H - Wyświetla nazwę pliku, w którym znajduje się tekst.
  • -c- Wyświetla liczbę pasujących linii. Można łączyć z -H.
kenorb
źródło
1
Uważam też, że przydatne jest rozszerzanie globowania. Należy jednak pamiętać, że jeśli naprawdę istnieje ogromna liczba plików, może pojawić się błąd „Zbyt długa lista argumentów”. (Proste globowanie jest również podatne na tego rodzaju błędy).
Yoory N.
2
W przypadku wdychania całego systemu plików rg będzie znacznie mniej bolesne niż prawie każde inne narzędzie.
Łk
55

Jeśli grepnie obsługuje wyszukiwania rekurencyjnego, możesz połączyć findz xargs:

find / -type f | xargs grep 'text-to-find-here'

Uważam to za łatwiejsze do zapamiętania niż format find -exec.

Spowoduje to wyświetlenie nazwy pliku i zawartości dopasowanego wiersza, np

/home/rob/file:text-to-find-here

Opcjonalne flagi, które możesz dodać do grep:

  • -i - wyszukiwanie bez rozróżniania wielkości liter
  • -l - wypisuje tylko nazwę pliku, w którym znaleziono dopasowanie
  • -h - wypisuje tylko pasujący wiersz (nie nazwę pliku)
RobEarl
źródło
3
Jest to równoważne grep 'text-to-find-here'bez nazwy pliku, jeśli findniczego nie znajdzie. To się zawiesi i zaczeka na dane wejściowe użytkownika! Dodaj --no-run-if-emptyjako opcję do xargs.
hagello
3
Ta kombinacja find i xargs nie działa zgodnie z przeznaczeniem, jeśli nazwy plików lub katalogów zawierają spacje (znaki, które xargs interpretuje jako separatory). Zastosowanie find … -exec grep … +. Jeśli nalegasz na używanie find razem z xargs, użyj -print0i -0.
hagello
43
grep -insr "pattern" *
  • i: Zignoruj ​​rozróżnienie wielkości liter zarówno w WZORZE, jak i plikach wejściowych.
  • n: Poprzedź każdą linię wyjścia numerem linii na podstawie 1 w swoim pliku wejściowym.
  • s: Pomiń komunikaty o błędach dotyczące nieistniejących lub nieczytelnych plików.
  • r: Rekurencyjnie czytaj wszystkie pliki w każdym katalogu.
enfinet
źródło
3
Czy potrafisz wyjaśnić, w jaki sposób twoja odpowiedź poprawia się w porównaniu z innymi odpowiedziami lub w jaki sposób różni się od nich wystarczająco?
Amos M. Carpenter
niezbyt skomplikowany do zapamiętania, obejmie wszystkie wzorce (rozróżnianie wielkości liter -> wyłączone, obejmuje nazwy plików i numery wierszy oraz będzie wyszukiwał rekurencyjnie itp.), a użycie „*” na końcu przeszuka wszystkie katalogi (nie trzeba podawać żadnych ścieżka lub nazwa katalogu).
enfinet
Przepraszam, powinienem był wyjaśnić: byłoby wspaniale, gdybyś umieścił to wyjaśnienie w swojej odpowiedzi. W obecnej formie, zwłaszcza przy tak wielu innych podobnych odpowiedziach, z tak krótkiej odpowiedzi trudno jest zobaczyć, jaka byłaby korzyść z wypróbowania jej w stosunku do odpowiedzi zaakceptowanej lub jednej z ocenionych.
Amos M. Carpenter
6
@ AmosM.Carpenter Jedną z rzeczy, które uwielbiam w tej odpowiedzi, jest wskazanie argumentu tłumienia, który może pomóc odfiltrować szum, który nie ma znaczenia dla uzyskania oczekiwanych rezultatów. Grep drukuje na niektórych „plikach” błędy takie jak: „Funkcja nie została zaimplementowana”, „Nieprawidłowy argument”, „Zasób niedostępny” itp.
leetNightshade
@leetNightshade: Zakładam, że adresujesz swój komentarz do mnie, ponieważ poprosiłem o wyjaśnienie rzadkiego oryginalnego postu. Zapoznaj się ze świetną wersją Fabio, aby moje poprzednie komentarze miały sens.
Amos M. Carpenter
39

Istnieje nowe narzędzie o nazwie The Silversearcher

sudo apt install silversearcher-ag

Działa ściśle z Git i innymi VCS. Więc nic nie dostaniesz w .git lub innym katalogu.

Możesz po prostu użyć

ag "Search query"

I zrobi to za Ciebie!

Neil Agarwal
źródło
35

Jak znaleźć wszystkie pliki zawierające określony tekst w systemie Linux? (...)

Dwukrotnie natrafiłem na to rozwiązanie:

find / -type f -exec grep -H 'text-to-find-here' {} \;


W przypadku korzystania find jak w przykładzie, lepiej dodać -s( --no-messages) w celu grepi 2>/dev/nullna końcu polecenia do wielu Unikać Permission denied komunikaty wydawane przez grepi find:

find / -type f -exec grep -sH 'text-to-find-here' {} \; 2>/dev/null

find jest standardowym narzędziem do wyszukiwania plików - w połączeniu z grep podczas wyszukiwania określonego tekstu - na platformach typu Unix. Find polecenie jest często w połączeniu z xargs , tak przy okazji.

Istnieją szybsze i łatwiejsze narzędzia do tego samego celu - patrz poniżej. Lepiej je wypróbuj, pod warunkiem, że są one dostępne na twojej platformie , oczywiście:

Szybsze i łatwiejsze alternatywy

RipGrep - najszybsze narzędzie wyszukiwania:

rg 'text-to-find-here' / -l

Srebrny Poszukiwacz :

ag 'text-to-find-here' / -l

ack :

ack 'text-to-find-here' / -l

Uwaga: Możesz również dodać 2>/dev/nulldo tych poleceń, aby ukryć wiele komunikatów o błędach.


Ostrzeżenie : chyba że naprawdę nie możesz tego uniknąć, nie wyszukuj z '/' (katalogu głównego), aby uniknąć długiego i nieefektywnego wyszukiwania! Dlatego w powyższych przykładach lepiej zastąpić „ / ” nazwą podkatalogu, np. „/ Home”, w zależności od tego, gdzie faktycznie chcesz wyszukać ...

Bludzee
źródło
„find to standardowe narzędzie do wyszukiwania plików zawierających określony tekst na platformach typu Unix” wydaje mi się dość dwuznaczne. Nawet poza tym, że rekursywny grep findnie przeszukuje bezpośrednio plików wewnątrz tekstu. I może te dodatkowe narzędzia są przydatne dla niektórych, ale starych timerów, a ci, do których są przyzwyczajeni, np. W grepogóle nie dadzą im czasu (cóż, na pewno nie zrobię tego). Nie mówię jednak, że są bezużyteczne.
Pryftan
„.... zawierający konkretny tekst ...”: ta część zdania nie była dokładna (ponieważ to nie ona sama zajmuje się tą częścią wyszukiwania). Edytowane. Dzięki.
Bludzee
Cieszę się, że mogę pomóc! Jedyną rzeczą, na bardzo szybkie spojrzenie, jest zmiana folderu słów na katalog, ale wiem, że to moja krucjata, której nigdy nie wygram całkowicie. Nie
poddawaj
Dlaczego nie „katalog” zamiast „folder”, ale dlaczego? Podziel się swoją „krucjatą”!
Bludzee
Mówię zamiast tego użyj katalogu! Odnosząc się do: lepiej zastąp „/” nazwą podfolderu I to jest mój wkurzony zwierzak… szczególnie, że nawet Windows zwykł nazywać go „katalogiem”. Ach ... może masz to. Dlaczego? Cóż, bo tak się nazywa. Nazywa się to również na poziomie systemu plików. I spójrz na to w ten sposób: czy kiedykolwiek był nazywany (dla DOS) fol? Nie, oczywiście nie; został nazwany dir(i wierzę, że nadal tak jest). Folder jest zaprojektowany dla (jak sądzę) przyjazności dla użytkownika, chociaż w tym przypadku może być głupszy dla mniej „zaawansowanych” użytkowników?
Pryftan
29

Próbować:

find . -name "*.txt" | xargs grep -i "text_pattern"
venkat
źródło
5
To jest naprawdę najlepszy przykład, kiedy NIE należy tego używać xargs. Rozważ to. echo "file bar.txt has bar" > bar.txt; echo "file foo bar.txt has foo bar" > "foo bar.txt"; echo "You should never see this foo" > foo; find . -name "*.txt" | xargs grep -i foo # ./foo:You should never see this foo. xargsTutaj dopasowany plik źle i nie pasuje do zamierzonego pliku. Albo użyj find .. -print0 | xargs -0 ...ale, ale to bezużyteczne użycie fajki lub lepiejfind ... -exec grep ... {} +
shalomb
29

Służy pwddo wyszukiwania z dowolnego katalogu, w którym się znajdujesz, powtarzając w dół

grep -rnw `pwd` -e "pattern"

Aktualizacja W zależności od używanej wersji grep możesz pominąć pwd. W nowszych wersjach .wydaje się, że domyślnym przypadkiem grep jest brak katalogu:

grep -rnw -e "pattern"

lub

grep -rnw "pattern"

zrobi to samo co powyżej!

mahatmanich
źródło
3
używanie pwdnie jest wcale konieczne, ponieważ jest to ustawienie domyślne. grep -rnw "pattern"wystarczy.
fedorqui „SO przestań szkodzić”
i tak naprawdę na grep -rnwto samo pytanie udzielono trzy lata temu, nie rozumiem, w jaki sposób ta odpowiedź stanowi wartość dodaną.
fedorqui „SO przestań szkodzić”
Wybrana odpowiedź nie pokazuje domyślnego wzorca, a 5 osób uznało ją za przydatną
mahatmanich,
Co masz na myśli przez „domyślny wzór”? Akceptowana odpowiedź zawiera grep -rnw '/path/to/somewhere/' -e "pattern"to, co masz tutaj. 5 głosów po 2,3 mln wizyt nie znaczy tak wiele.
fedorqui „SO przestań szkodzić”
Zgadzam się :-) to, czego mi brakowało w oryginalnej odpowiedzi, to przypadek użycia, w którym nie musisz wcale podawać ścieżki lub przeszukiwać bieżącego katalogu rekurencyjnie, co nie znajduje odzwierciedlenia w zaakceptowanej odpowiedzi. Tak więc było to dobre doświadczenie edukacyjne na temat grep, aby kopać nieco głębiej.
mahatmanich,
19

grep można użyć, nawet jeśli nie szukamy łańcucha.

Po prostu działa,

grep -RIl "" .

wypisze ścieżkę do wszystkich plików tekstowych, tj. zawierających tylko znaki do wydrukowania.

Alex Jasmin
źródło
2
Nie rozumiem, jak to jest lepsze niż używanie zwykłego lslub find(dla rekurencyjnego)
fedorqui „SO przestań krzywdzić”
17

Oto kilka list poleceń, których można użyć do wyszukiwania pliku.

grep "text string to search” directory-path

grep [option] "text string to search” directory-path

grep -r "text string to search” directory-path

grep -r -H "text string to search” directory-path

egrep -R "word-1|word-2” directory-path

egrep -w -R "word-1|word-2” directory-path
Atul Arvind
źródło
5
co to dodaje do istniejących odpowiedzi?
fedorqui „SO przestań szkodzić”
@fedorqui egrepjest równoważne grep -Ei oznacza, --extended-regexpże możesz znaleźć szczegóły tutaj unix.stackexchange.com/a/17951/196072
omerhakanbilici
15
find /path -type f -exec grep -l "string" {} \;

Wyjaśnienie z komentarzy

find to polecenie, które pozwala znaleźć pliki i inne obiekty, takie jak katalogi i łącza w podkatalogach danej ścieżki. Jeśli nie określisz maski, którą nazwy plików powinny spełniać, wyliczy wszystkie obiekty katalogu.

-type f specifies that it should proceed only files, not directories etc.
-exec grep specifies that for every found file, it should run grep command, passing its filename as an argument to it, by replacing {} with the filename
Vinod Joshi
źródło
15

Próbować:

find / -type f -exec grep -H 'text-to-find-here' {} \;

który przeszuka wszystkie systemy plików, ponieważ /jest to folder główny.

Do użytku w folderze domowym:

find ~/ -type f -exec grep -H 'text-to-find-here' {} \;

Do bieżącego folderu użyj:

find ./ -type f -exec grep -H 'text-to-find-here' {} \;
użytkownik4863663
źródło
Być może szczegóły dotyczące różnic folderów są oczywiste dla wielu ... ale także bardzo pomocne dla początkujących. +1
nilon
1
co to dodaje do istniejących odpowiedzi?
fedorqui „SO przestań szkodzić”
Nazwij to moją krucjatą, ale słowo to „katalog”. To nie jest Windows (który i tak używał „katalogu” - wcześniej niż 9x). Proszę przestać mówić „folder”. Jeśli chodzi o twoje ostatnie polecenie, nie potrzebujesz nawet „/” po prostu FYI.
Pryftan
15

Mam nadzieję, że to pomoże ...

Rozwijając grepnieco, aby uzyskać więcej informacji w danych wyjściowych, na przykład, aby uzyskać numer wiersza w pliku, w którym znajduje się tekst, można wykonać w następujący sposób:

find . -type f -name "*.*" -print0 | xargs --null grep --with-filename --line-number --no-messages --color --ignore-case "searthtext"

A jeśli masz pojęcie, jaki jest typ pliku, możesz zawęzić wyszukiwanie, określając rozszerzenia typów plików do wyszukania, w tym przypadku .pasLUB .dfmpliki:

find . -type f \( -name "*.pas" -o -name "*.dfm" \) -print0 | xargs --null grep --with-filename --line-number --no-messages --color --ignore-case "searchtext"

Krótkie wyjaśnienie opcji:

  1. .w findokreśla z bieżącego katalogu.
  2. -name*.*”: Dla wszystkich plików (-name „ *.pas” -o -name „ *.dfm”): Tylko *.pasLUB *.dfmplików lub określony z-o
  3. -type f określa, że ​​szukasz plików
  4. -print0a --nullpo drugiej stronie |(potoku) są najważniejsze, przekazując nazwę pliku z finddo greposadzonego w xargs, umożliwiając przekazywanie nazw plików ze spacjami w nazwach plików, pozwalając grepowi traktować ścieżkę i nazwę pliku jako jeden ciąg, i nie rozbijaj go na każdym polu.
Gert van Biljon
źródło
-name '*.*'nie jest tym, co mówisz; nie przechwyciłby pliku o nazwie „plik”, ponieważ wzorzec nie jest z nim zgodny (brak .ext); *zrobiłby jednak (oprócz plików. na bok). Ale jest jeszcze jedna rzecz: jeśli chcesz wszystkie pliki, po co zawracać sobie głowę określaniem nazwy pliku? Żadnego innego komentarza - poza tym, że miło jest wiedzieć, że wciąż są ludzie, którzy nie używają terminologii MS „folder” (który tak naprawdę po powiedzeniu tego wystarczająco dużo nie dodałbym, ale chciałem zwrócić uwagę na nieco niepoprawne stwierdzenie, które wypowiedziałeś z nazwami plików - a także nadmiarowością / bezużytecznością w przypadku „wszystkich”).
Pryftan
15

Prosty findmoże się przydać. alias w twoim ~/.bashrcpliku:

alias ffind find / -type f | xargs grep

Uruchom nowy terminal i wydaj:

ffind 'text-to-find-here'
zwisający wskaźnik
źródło
14

Napisałem skrypt w języku Python, który robi coś podobnego. Tak należy używać tego skryptu.

./sniff.py path pattern_to_search [file_pattern]

Pierwszym argumentem pathjest katalog, w którym będziemy przeszukiwać rekurencyjnie. Drugi argument, pattern_to_searchto wyrażenie regularne, które chcemy wyszukać w pliku. Używamy formatu wyrażeń regularnych zdefiniowanych w bibliotece Python re . W tym skrypcie .również pasuje do znaku nowej linii.

Trzeci argument file_pattern, jest opcjonalny. To kolejne wyrażenie regularne, które działa na nazwie pliku. Uwzględnione zostaną tylko te pliki, które pasują do tego wyrażenia regularnego.

Na przykład, jeśli chcę wyszukiwać pliki Pythona z rozszerzeniem pyzawierającym Pool(następujące po nim słowo Adaptor, wykonuję następujące czynności,

./sniff.py . "Pool(.*?Adaptor"  .*py
./Demos/snippets/cubeMeshSigNeur.py:146 
./Demos/snippets/testSigNeur.py:259 
./python/moose/multiscale/core/mumbl.py:206 
./Demos/snippets/multiComptSigNeur.py:268 

I voila, generuje ścieżkę dopasowanych plików i numer linii, przy której znaleziono dopasowanie. Jeśli znaleziono więcej niż jedno dopasowanie, każdy numer wiersza zostanie dołączony do nazwy pliku.

Dilawar
źródło
14

Jeśli chcesz używać, findużyj find + grep:

find /path/to/somewhere/ -type f -exec grep -nw 'textPattern' {} \;

kroki:

1. Użyj finddo wyszukiwania plików, 2.
Następnie uruchom grepje wszystkie.

To daje moc findwyszukiwania plików.

  • Użyj, -name Patternjeśli chcesz greptylko niektóre pliki:

    find /path/to/somewhere/ -type f -name \*.cpp -exec grep -nw 'textPattern' {} \;

Możesz z nim grać i korzystać z różnych opcji findusprawnienia lub zawężenia wyszukiwania plików.

BreakBadSP
źródło
Jaka jest różnica? Czy będzie działać ze spacjami w ścieżce pliku?
Peter Mortensen
13

Posługiwać się:

grep -c Your_Pattern *

Spowoduje to podanie liczby kopii wzorca w każdym z plików w bieżącym katalogu.

Dr_Hope
źródło
13

grep jest twoim dobrym przyjacielem, aby to osiągnąć.

grep -r <text_fo_find> <directory>

Jeśli nie zależy Ci na wielkości tekstu, który chcesz znaleźć, użyj:

grep -ir <text_to_find> <directory>
Prash
źródło
W moim przypadku wygląda na to, że szuka wszędzie, nawet jeśli podam katalog
Pathros
@Pathros Prawdopodobnie ma to związek z włączoną rekurencją i podanym katalogiem. Innymi słowy, rekurencja zmienia rzeczy w ten sposób.
Pryftan
@Pathros Aha, a jeśli -w ciągu wyszukiwania są jakieś s, najpierw musisz przekazać --grep; które w przeciwnym razie mogą powodować ciekawe skutki uboczne!
Pryftan
13

Fascynuje mnie to, jak prosty grep robi to z „rl”:

grep -rl 'pattern_to_find' /path/where/to/find

-r to recursively find a file / directory inside directories..
-l to list files matching the 'pattern'

Użyj „-r” bez „l”, aby zobaczyć nazwy plików i tekst, w którym znajduje się wzorzec !

grep -r 'pattern_to_find' /path/where/to/find

Działa idealnie ...

nitinr708
źródło
Działa to również w Git Bash (Windows).
Peter Mortensen
Ale oznacza to, że każdy plik musi zostać przeszukany (bez filtra na nazwie pliku lub poziomie rozszerzenia pliku, jak .txt). Czy jest na to sposób?
Peter Mortensen
12

Aby wyszukać ciąg i wyprowadzić tylko ten wiersz z ciągiem wyszukiwania:

for i in $(find /path/of/target/directory -type f); do grep -i "the string to look for" "$i"; done

na przykład:

for i in $(find /usr/share/applications -type f); \
do grep -i "web browser" "$i"; done

Aby wyświetlić nazwę pliku zawierającą szukany ciąg:

for i in $(find /path/of/target/directory -type f); do if grep -i "the string to look for" "$i" > /dev/null; then echo "$i"; fi; done;

na przykład:

for i in $(find /usr/share/applications -type f); \
do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \
fi; done;

źródło
1
Widzę tylko minusy w porównaniu do używania find … -exec grep 'str' {} \;(jeśli musisz findw ogóle używać ).
phk
1
Spowodowałoby to okropne uszkodzenie, gdyby którykolwiek z plików znalezionych przez findzawarte spacje .. mógł spowodować greppingnieprawidłowe pliki i / lub całkowity brak odpowiednich plików. Po prostu użyj, find ... -exec grep ...jeśli musisz użyć find... ale w tym przypadku grep -r ...wystarczy.
shalomb
1
jaki jest sens używania pętli nad wynikami find, aby następnie grep? To staje się niepotrzebnie skomplikowane.
fedorqui „SO przestań szkodzić”
12

Istnieje acknarzędzie, które zrobiłoby dokładnie to, czego szukasz.

http://linux.die.net/man/1/ack

ack -i search_string folder_path/*

Możesz zignorować -iwyszukiwanie z rozróżnianiem wielkości liter

Kumpel
źródło
2
Co to dodaje do istniejących odpowiedzi? Zasugerowano to już ponad trzy lata temu.
fedorqui „SO przestań szkodzić”
1
@fedorqui 1) bez orurowania! 2) Używaj wyrażeń regularnych 3) Uzyskaj numery linii, nazwę pliku ze ścieżką względną, podświetlony tekst itp. Przydatne do edycji po wyszukiwaniu, np. „Vim + lineno path / file.cpp” przeniesie Cię bezpośrednio do linii, która Cię nie interesuje. Zobacz dane wyjściowe polecenia „ack include \ | hpp”, które wyszukuje słowa kluczowe „include” lub „hpp” w moim folderze wyszukiwania i podfolderach. Mam nadzieję, że punkt jest jasny. Oto przykładowy wynik (Nie można wyświetlić wyróżnienia słowa kluczowego za pomocą prostego tekstu) process / child.hpp 11: boost / process / child.hpp process / all.hpp 21: #include <boost / process / execute.hpp>
Pal
12

Wszystkie poprzednie odpowiedzi sugerują grep i find. Ale jest inny sposób: użyj Midnight Commander

Jest to darmowe narzędzie (30 lat, sprawdzone przez czas), które jest wizualne bez GUI. Ma mnóstwo funkcji, a wyszukiwanie plików to tylko jedna z nich.

Peter M. - oznacza Monikę
źródło
Strażnik miałby ten sam pomysł
nilon
11

Poniższe polecenie będzie działać dobrze dla tego podejścia:

find ./ -name "file_pattern_name"  -exec grep -r "pattern" {} \;
Pradeep Goswami
źródło
2
jaki jest sens używania, finda następnie grep -r? Są przeznaczone do tego samego, więc jest to zbędne.
fedorqui „SO przestań szkodzić”
och !! poprawione, Właściwie znajdź jest do uruchamiania grep na filtrowanych plikach i nie wszystko, dzięki
Pradeep Goswami
2
nadal nie ma to sensu, można filtrować za pomocą find.
fedorqui „SO przestań szkodzić”
11

Unikaj kłopotów i zainstaluj ack-grep. Eliminuje to wiele problemów związanych z pozwoleniami i ofertami.

apt-get install ack-grep

Następnie przejdź do katalogu, który chcesz przeszukać, i uruchom poniższe polecenie

cd /
ack-grep "find my keyword"
Kareem
źródło