2012-10-19 15 views
6

Obecnie używamKorzystanie regex w komendzie znaleźć dla wielu typów plików

find . -name '*.[cCHh][cC]' -exec grep -nHr "$1" {} ; \ 
find . -name '*.[cCHh]' -exec grep -nHr "$1" {} ; 

aby wyszukać ciąg w wszystkich plików kończąc .c, .c, .h, .H, .cc i .cc wymienione we wszystkich podkatalogach. Ale ponieważ obejmuje to dwa polecenia, wydaje się to nieefektywne.

Jak mogę użyć pojedynczego wzorca regex do znalezienia plików .c, .C, .h, .H, .cc i .CC?

Używam bash na komputerze z systemem Linux.

+2

BTW, argument do '-name' nie jest wyrażeniem regularnym, jest rozszerzeniem powłoki. – rid

Odpowiedz

14

Można użyć logiczną OR argument:

find -name '*.[ch]' -o -name '*.[CH]' -o -name '*.cc' -o -name '*.CC' 

Powyższy znajdzie pliki, które kończą się w:

  • .c, .h LUB
  • .C, .H LUB
  • .cc LUB
  • .CC.
+3

O wiele bardziej elegancka niż próba wykonania tego wszystkiego za pomocą wyrażeń regularnych. –

+0

To nie działa, jeśli chcesz dodać "-exec". Na przykład "find -name \ * .log" -o -name \ *. Txt -exec cat '{}' \; "Wykonuje tylko pierwszą nazwę – OutputLogic

+0

, która z jakiegoś powodu nie zdaje sobie sprawy, że' - o ' – Crowie

0

find . -regex '.*\.\([chCH]\|cc\|CC\)'
znajdzie wszystkie pliki o nazwach kończących się w .c, .C, .h, .H, .cc i .cc i nie znaleźć żadnego w tym celu w .HC, .cc, lub. DW. W wyrażeniu regularnym pierwsze kilka znaków pasuje do ostatniego okresu w nazwie, a nawiasowe alternatywy pasują do pojedynczego znaku c, h, C lub H, albo do cc lub CC.

uwaga, znaleźć w -regex i -iregex przełączniki są analogiczne do -name i -iname, ale przełącza regex typu pozwalają wyrażeń regularnych z | dla alternatywnych meczów. Podobnie jak -iname, -iregex rozróżnia wielkość liter.

The (niefunkcjonalne) Forma
find . -name '*.[cCHh][cC]?$'
podane w poprzedniej odpowiedzi nie wymienia żadnych nazwisk w moim systemie Linux z GNU znaleźć 4.4.2. Kolejnym problemem z '*.[cCHh][cC]?$' jako wyrażeniem regularnym jest to, że będzie pasować do nazw takich jak abc.Cc i xyz.hc, które nie znajdują się w zbiorze plików .c, .C, .h, .H, .cc i .CC, które chcesz.

+0

pierwsza forma nie działa, ponieważ '?' I '$' nie są wzorami powłoki, więc są interpretowane dosłownie – doubleDown

+0

@rid, ja zredagowałem by wskazać, że '-iregex '. * \. [Ch] \ |. * \ .cc''s * not * pasuje do .cH. Zgadzam się jednak, że pasuje ona do .Cc i .cC i dodaje '-regex dla dokładnego zestawu rozszerzeń –

11

To powinno działać

Messy

find . -iregex '.*\.\(c\|cc\|h\)' -exec grep -nHr "$1" {} ; 

-iregex przez przypadek-niewrażliwe regex wzorca.

(c|cc|h) (paskudne ucieczek nie pokazane) dopasowuje C, CC, lub H rozszerzeń


Clean

find -regextype "posix-extended" -iregex '.*\.(c|cc|h)' -exec grep -nHr "$1" {} ; 

Funkcja ta znajdzie .cc i.również rozszerzenia cC. Zostałeś ostrzeżony.

1

To polecenie działa.

find -regextype posix-extended -regex '.+\.(h|H|c{1,2}|C{1,2})$' 

Chciałbym móc użyć iregex. iregex również znalazłby .Cc i .cC. Gdybym mógł, polecenie wyglądałoby tak. Trochę krótszy.

find -regextype posix-extended -iregex '.+\.(h|H|c{1,2})$' 
Powiązane problemy