Jak mogę „grep” rekurencyjnie filtrować nazwy żądanych plików za pomocą symboli wieloznacznych?

40

Kiedy chcę przeprowadzić rekurencyjne wyszukiwanie grep w bieżącym katalogu, zwykle robię:

grep -ir "string" .

Ale to polecenie przeszukuje wszystkie rodzaje plików, w tym pliki binarne (obrazy, audio, wideo itp.), Co powoduje bardzo powolny proces wyszukiwania.

Jeśli to zrobię, na przykład nie zadziała:

grep -ir "string" *.php

Nie działa, ponieważ w bieżącym katalogu nie ma plików PHP, ale w niektórych podkatalogach w bieżącym katalogu, a nazwy podkatalogów nie kończą się na „.php”, więc grep nie zagląda do nich.

Jak więc mogę przeprowadzić wyszukiwanie rekurencyjne z bieżącego katalogu, ale także podać symbole wieloznaczne nazw plików? (tzn .: szukaj tylko w plikach, które kończą się określonym rozszerzeniem)

OMA
źródło

Odpowiedzi:

58

Skorzystaj grep„s --includeopcja:

grep -ir "string" --include="*.php" .
Dan D.
źródło
1
Ok, wygląda na to, że moja wersja grep była stara, ponieważ nie miała tej opcji (nic dziwnego, dlaczego nie mogłem wymyślić, jak to zrobić!). Otrzymałem komunikat: „grep: nierozpoznana opcja„ --include = *. Php ””. Ale właśnie uaktualniłem do nowszego i teraz działa. Dziękuję Ci!
OMA
Musiałem wymienić kropkę na końcu i użyć:grep -ir "string" --include="*.php" *
Stuart
Myślałem, że kropka to tylko koniec linii! Nie korzystałem ani nie potrzebowałem.
boardtc
14

Jeśli masz wersję, grepktórej brakuje tej --includeopcji, możesz użyć następujących opcji. Oba zostały przetestowane na takiej strukturze katalogów:

$ tree
.
├── a
├── b
   └── foo2.php
├── c
   └── d
       └── e
           └── f
               └── g
                   └── h
                       └── foo.php
├── foo1.php
└── foo.php

Gdzie wszystkie .phppliki zawierają ciąg string.

  1. Posługiwać się find

    $ find . -name '*php' -exec grep -H string {} +
    ./b/foo2.php:string
    ./foo1.php:string
    ./c/d/e/f/g/h/foo.php:string

    Wyjaśnienie

    To znajdzie wszystkie .phppliki, a następnie uruchomi się grep -H stringna każdym z nich. Z find„s -execopcji {}otrzymuje każda ze znalezionych plików. -HMówi grepwydrukować nazwę pliku, a także dopasowaną linię.

  2. Zakładając, że masz wystarczająco nową wersję bash, użyj globstar:

    $ shopt -s globstar
    $ grep -H string  **/*php
    b/foo2.php:string
    c/d/e/f/g/h/foo.php:string
    foo1.php:string

    Wyjaśnienie

    Jak wyjaśniono w podręczniku bash :

    globstar

    Jeśli jest ustawiony, wzorzec „**” użyty w kontekście rozszerzenia nazwy pliku będzie pasował do wszystkich plików i zero lub więcej katalogów i podkatalogów. Jeśli po wzorcu następuje „/”, pasują tylko katalogi i podkatalogi.

    Tak więc, uruchamiając shopt -s globstar, aktywujesz funkcję i globstaropcję Bash, która powoduje **/*phprozwinięcie do wszystkich .phpplików w bieżącym katalogu ( **dopasowuje 0 lub więcej katalogów, więc **/*phppasuje ./foo.phprównież), które są następnie wyszukiwane string.

terdon
źródło
-2

Posługiwać się */*.php

To sprawia, że ​​wyszukiwanie grep jest o jeden poziom podkatalogu

Dennis Nolan
źródło
Coś poszło nie tak, gdy zniknęły gwiazdki i kropki.
Dennis Nolan,
Możesz użyć odwrotnych znaków do sformatowania kodu i uniknąć dwuznaczności na temat używania gwiazdek do podkreślenia w formatowaniu przeceny. PS zauważa, że ​​pytanie zawiera pytanie o „wyszukiwanie rekurencyjne” w ostatnim akapicie (choć nie moje zdanie negatywne).
RedGrittyBrick,
Niepoprawna odpowiedź, ponieważ jest dobra tylko dla struktur głębokiego katalogu na jednym poziomie, jak wspomniałeś, ale mimo to dobrze wiedzieć;). Mój głos za to.
OMA