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
, xargs
oraz 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?
*
na'*'
: „Aby uniknąć błędów, gdy nazwa pliku zaczyna się od -”, należy podać ostatni znak zastępczy - ”-Msomething
lubGREP_OPTIONS
ustawienie.grep -r searchpattern /path/to/start/in
Gdzie
/path/to/start/in/
może być tylko „.
” dla bieżącego katalogu.źródło
Nie.
find -name \*.h -print0 | xargs -0 grep -l 'the regex'
Jest tak magiczna, jak to tylko możliwe.źródło
-r
opcją. Ciężka artyleria nie potrzebuje.xargs
dodaje tylko hałas. Użyjfind -name \*.h -execdir grep -l 'the regex {} +
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 dla
grep
.Jak wspomniano w innych odpowiedziach, implementacja GNU
grep
ma 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.
źródło
Aby znaleźć ciąg z danego katalogu, użyj poniższej komendy
Na przykład:
źródło
grep
może przyjmować więcej niż jeden plik jako argument, więc powinieneś użyć+
zamiast,\;
aby uniknąć uruchamiania jednegogrep
wywołania na plik, co jest dość nieefektywne.-name '*'
ogranicza się do plików, których nazwa jest poprawnym tekstem w bieżących ustawieniach regionalnych (find
przynajmniej 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łbyfind
schodzić do katalogów o niepoprawnych nazwach.