Znajdowanie plików zawierających określony ciąg znaków za pomocą find (1) i grep (1)

70

find . -type f -print -exec cat {} \; | grep some string

Powyższe polecenie nie drukuje ścieżki do pliku.

Używam: Ubuntu, bash 4.

H.Rabiee
źródło
Być może nie spełnia oczekiwanych wyników z powodu filtra grep. A co z tym:find . -type f -fprint /dev/stderr -exec cat {} \; | grep some string
artistoex,
Jaki jest cel, który chcesz osiągnąć? Na wyjściu otrzymujesz grepowane ciągi z plików, chcesz ścieżkę do tych plików?
mirkobrankovic
Tak, chcę wydrukować ścieżkę do plików zawierających ciąg „jakiś ciąg”. Sugestia @artistoex drukuje wszystkie ścieżki plików.
H.Rabiee
Możesz po prostu użyć ackdo przeszukania wszystkich plików w bieżącym katalogu, prawdopodobnie filtrując tylko niektóre typy plików.
Jaap Eldering

Odpowiedzi:

87

To dlatego, że podajesz grepstrumień tekstu, który akurat zawiera nazwy plików. Ponieważ nie podano żadnych nazw plików jako argumentów grep, nie można oczekiwać, że wydedukuje, z którego pliku pochodzi dopasowana linia. Użyj xargs:

find . -type f -print | xargs grep "some string"

Ponieważ masz GNU find / xargs, jest to bezpieczniejszy sposób dla xargs na czytanie nazw plików:

find . -type f -print0 | xargs -0 grep "some string"

Jeśli chcesz tylko nazwy plików, które mają pasującą linię, bez pokazywania pasującej linii:

find . -type f -print0 | xargs -0 grep -l "some string"
Glenn Jackman
źródło
Jak mam połączyć powyższe polecenia z wyszukiwaniem i zamianą? Jak w, grep następnie sed?
CMCDragonkai
1
potok find | grep wyświetla nazwy plików, więc:sed '...' $(find ... | xargs grep -l ...)
glenn jackman
107

używam

grep "some string" . -R

i działa szybciej

ps

Bardziej złożony przypadek użycia

grep -HiRE "some string|other string" . #H for file printing, i for case-insensitive, R for recursive search, E for regex 

Aby przeczytać wyjaśnienie param i

grep --help | grep -- -i
ArcherGodson
źródło
17
A -njeśli chcesz numery linii. +1 za uproszczoną odpowiedź.
Chad Skeeters
@ChadSkeeters dokładnie. Korzystanie ze znaleziska nie daje takiego rozwiązania.
ArcherGodson
1
Szczerze mówiąc, należy to zaznaczyć jako prawidłową odpowiedź. Obecnie wybrany jeden szczegółowo opisuje coś jeszcze.
11

Często szukam kodu źródłowego w złożonych strukturach folderów i uznaję za przydatne:

cd /your/folder/
grep -rHino "your string"

Dzięki tym parametrom, bez użycia find , uzyskuję pełną ścieżkę do pliku i numer wiersza, który zawiera określony ciąg .

Jest to również łatwe do zapamiętania, ponieważ BASH es poprzez wyszukiwania jak Rhino :)

Pokażę, jak to działa, na krótkim przykładzie.

Wyświetlmy zawartość pliku za pomocą cat:

jeeves ~ # cat fw.stop
#!/bin/sh
echo "Stopping firewall and allowing everyone..."
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

Przeszukujmy rekurencyjnie wszystkie pliki zawierające ciąg „iptables -P”:

jeeves ~ # grep -rinHo "iptables -P"
fw.stop:9:iptables -P
fw.stop:10:iptables -P
fw.stop:11:iptables -P

Jak widać na wyjściu, mamy nazwę pliku: hit row: szukany ciąg

Oto bardziej szczegółowy opis używanych parametrów:

-r Dla każdego operandu katalogu, rekurencyjnie odczytuj i przetwarzaj wszystkie pliki w tym katalogu. Podążaj za dowiązaniami symbolicznymi w linii poleceń, ale pomiń dowiązania symboliczne, które występują rekurencyjnie. Zauważ, że jeśli nie podano operandu pliku, grep przeszukuje katalog roboczy. Jest to to samo, co opcja „--directories = recurse”.

-i Wydrukuj nazwę pliku dla każdego dopasowania. Jest to ustawienie domyślne, gdy istnieje więcej niż jeden plik do przeszukania.

-n Prefiks każdego wiersza wyjścia numerem linii na podstawie 1 w swoim pliku wejściowym. (-n jest określone przez POSIX).

-H Wydrukuj nazwę pliku dla każdego dopasowania. Jest to ustawienie domyślne, gdy istnieje więcej niż jeden plik do przeszukania.

-o Drukuj tylko dopasowane (niepuste) części pasujących linii, przy czym każda taka część znajduje się w osobnej linii wyjściowej. Linie wyjściowe używają tych samych separatorów co dane wejściowe, a separatory są bajtami zerowymi, jeśli użyto również opcji -z (--null-data) (zobacz Inne opcje).

Pitto
źródło
1

Wolałem

| znajdź plik | make grep ont znajdź plik | pokaż pełną ścieżkę do pliku

znajdź / -type f -exec grep 'some string' {} \; -exec echo {} \;

użytkownik515185
źródło
0

Silver Searcher to bardzo szybkie i wygodne narzędzie do wyszukiwania plików i treści.

Aby rozwiązać problem, polecenie srebrnego wyszukiwania będzie wyglądać tak ...

ag 'some string' -l

-l Drukuj tylko nazwy plików zawierające dopasowania (nie drukuj pasujących wierszy)

qoomon
źródło