Znaleźć podciąg w plikach w podkatalogach za pomocą jednego wbudowanego polecenia?


10

W systemie Windows, gdybym chciał znaleźć ciąg znaków we wszystkich plikach we wszystkich podkatalogach, zrobiłbym coś takiego

findstr /C:"the string" /S *.h

Jednak w systemie Linux (powiedzmy, Ubuntu) znalazłem innego sposobu niż niektóre rurami polecenia udziałem find, xargsoraz grep(przykładem jest na tej stronie: ? Jak mogę rekursywnie grep poprzez podkatalogów ). Moje pytanie jest jednak inne: czy jest jakieś wbudowane polecenie, które działa przez tę magię, bez konieczności pisania skryptu powłoki?

Odpowiedzi:


19

GNU grep pozwala na rekurencyjne wyszukiwanie w podkatalogach:

grep -r --include='*.h' 'the string' .

Wypróbowałem dokładnie ten wiersz poleceń w Ubuntu, ale otrzymałem „grep: nieprawidłowa opcja -„ M ””, chociaż nigdzie nie widzę żadnego „M” ... zagadkowe
Guido Domenici

@Guido działa tutaj dobrze
phunehehe

W sugerowanej edycji TomasG zaleca zmianę ostatniego *na '*': „Aby uniknąć błędów, gdy nazwa pliku zaczyna się od -”, należy podać ostatni znak zastępczy - ”
Michael Mrozek

Dziwny zbieg wydarzeń, teraz działa również dla mnie, jak podano w pierwotnej odpowiedzi. Dzięki!
Guido Domenici

1
@Guido: Przyczyną problemu może być plik w bieżącym katalogu o nazwie -Msomethinglub GREP_OPTIONSustawienie.
Gilles „SO- przestań być zły”

2

grep -r searchpattern /path/to/start/in

Gdzie /path/to/start/in/może być tylko „ .” dla bieżącego katalogu.



0

czy jest jakieś wbudowane polecenie, które działa dzięki tej magii ...?

Mówiąc pedantycznie, nie, nie można zakładać, że takie polecenie istnieje .

Istnieje wiele różnych implementacji Uniksa, a każda z nich ma swoje inne dziwactwa. POSIX, wspólny mianownik (i najbliższy standardowi w Unices) nie określa takiej opcji dlagrep .

Jak wspomniano w innych odpowiedziach, implementacja GNU grepma niestandardową opcję, która robi to, co chcesz. Chociaż ta konkretna implementacja może być powszechna w systemach Linux, nie można zakładać jej dostępności w żadnym systemie Unix, nawet w niektórych systemach Linux.

Na koniec powinienem wspomnieć, że filozofią Uniksa jest faworyzowanie kombinacji kilku prymitywnych programów, zamiast korzystania z jednego dużego monolitycznego pliku wykonywalnego, który próbuje zrobić wszystko na raz.

W twoim przypadku przeszukiwanie systemu plików i dopasowanie wyrażenia regularnego w strumieniu to dwa osobne zadania. Każdy jest traktowany osobno w osobnym programie.


0

Aby znaleźć ciąg z danego katalogu, użyj poniższej komendy

find <fullDirectoryPath> -name '*' -exec grep -l '<StringToFind>' {} \;

Na przykład:

find /apps_bev/apps/xfer/export/02210 -name '*' -exec grep -l '38221000001032' {} \;

1
grepmoże przyjmować więcej niż jeden plik jako argument, więc powinieneś użyć +zamiast, \;aby uniknąć uruchamiania jednego grepwywołania na plik, co jest dość nieefektywne.
Stéphane Chazelas,

1
Należy pamiętać, że -name '*'ogranicza się do plików, których nazwa jest poprawnym tekstem w bieżących ustawieniach regionalnych ( findprzynajmniej w niektórych implementacjach), ale inne komponenty katalogu mogą nadal zawierać sekwencje bajtów, które nie tworzą prawidłowych znaków. Jeśli Twoim celem -name '*'było upewnienie się, że wynik jest prawidłowy (pomijając pliki o niepoprawnych nazwach), wolisz użyć find ... ! -name '*' -prune -o -exec grep ... {} +, który również przestałby findschodzić do katalogów o niepoprawnych nazwach.
Stéphane Chazelas,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.