Jak używać wyrażenia regularnego z poleceniem find?


297

Mam kilka obrazów o nazwach z wygenerowanym ciągiem uuid1. Na przykład 81397018-b84a-11e0-9d2a-001b77dc0bed.jpg. Chcę znaleźć wszystkie te obrazy za pomocą polecenia „znajdź”:

find . -regex "[a-f0-9\-]\{36\}\.jpg".

Ale to nie działa. Coś nie tak z wyrażeniem regularnym? Czy ktoś mógłby mi w tym pomóc?


7
może zmienić typ wyrażenia regularnego. Domyślnie są to wyrażenia regularne Emacsa , cokolwiek to znaczy.
pavium

Odpowiedzi:


348
find . -regextype sed -regex ".*/[a-f0-9\-]\{36\}\.jpg"

Pamiętaj, że musisz określić .*/na początku, ponieważ findpasuje do całej ścieżki.

Przykład:

susam@nifty:~/so$ find . -name "*.jpg"
./foo-111.jpg
./test/81397018-b84a-11e0-9d2a-001b77dc0bed.jpg
./81397018-b84a-11e0-9d2a-001b77dc0bed.jpg
susam@nifty:~/so$ 
susam@nifty:~/so$ find . -regextype sed -regex ".*/[a-f0-9\-]\{36\}\.jpg"
./test/81397018-b84a-11e0-9d2a-001b77dc0bed.jpg
./81397018-b84a-11e0-9d2a-001b77dc0bed.jpg

Moja wersja find:

$ find --version
find (GNU findutils) 4.4.2
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Built using GNU gnulib version e5573b1bad88bfabcda181b9e0125fb0c52b7d3b
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION FTS() CBO(level=0) 
susam@nifty:~/so$ 
susam@nifty:~/so$ find . -regextype foo -regex ".*/[a-f0-9\-]\{36\}\.jpg"
find: Unknown regular expression type `foo'; valid types are `findutils-default', `awk', `egrep', `ed', `emacs', `gnu-awk', `grep', `posix-awk', `posix-basic', `posix-egrep', `posix-extended', `posix-minimal-basic', `sed'.

4
@Tom to sposób, w jaki wyrażenie regularne w znajdowaniu działa. Według strony podręcznika, wyrażenie regularne pasuje do całej ścieżki pliku, łącznie z katalogami, co oznacza, że ​​istnieje niejawne "^ ... $"otoczenie wyrażenia regularnego. Musi pasować do CAŁEJ linii wynikowej.
Manny D

2
Nie sądzę, że potrzebne są /w .*/ponieważ .*dopasowuje zero lub więcej (prawie) dowolnego znaku.
Jeff

2
Dla tych (takich jak ja), którzy nie przeczytali poprawnie wyrażenia regularnego po raz pierwszy: Zwróć uwagę na odwrotne ukośniki poprzedzające specjalne znaki wyrażenia regularnego, np .:\{36\}
Lucas Wilson-Richter

11
Miałem problem ze znalezieniem pełnej listy typów wyrażeń regularnych (strona nie jest aktualna):valid types are 'findutils-default', 'awk', ' egrep', 'ed', 'emacs', 'gnu-awk', 'grep', 'posix-awk', 'posix-basic', 'posix-egrep', 'posix -extended', 'posix-minimal-basic', 'sed'.
Noah Sussman

4
Upewnij się, aby umieścić -regextypeflagę przed tym -regexflagi, inaczej to nie ma zastosowania!
Christopher Orr,

84

-regexWyrażenie find dopasowuje całą nazwę , włączając względną ścieżkę z bieżącego katalogu. Do find .tego zawsze zaczyna się od ./, a następnie katalogów.

Są to również emacswyrażenia regularne, które mają inne reguły ucieczki niż zwykłe wyrażenia regularne egrep.

Jeśli wszystkie znajdują się bezpośrednio w bieżącym katalogu, to

find . -regex '\./[a-f0-9\-]\{36\}\.jpg'

powinno działać. (Nie jestem do końca pewien - nie mogę uruchomić liczonego powtórzenia). Możesz przełączyć się na wyrażenia egrep poprzez -regextype posix-egrep:

find . -regextype posix-egrep -regex '\./[a-f0-9\-]{36}\.jpg'

(Zauważ, że wszystko, co tu powiedziano, dotyczy GNU find, nie wiem nic o BSD, który jest również domyślny na Macu.)


1
Miałem nawias dla wielu pasujących ciągów w moim wyrażeniu regularnym, więc ten posix-egreptyp działał dla mnie.
palswim

2
Coś, na co należy zwrócić uwagę, -regextypejest opcją dla GNU, finda nie BSD (przynajmniej nie podobną do Mac BSD) find. Jeśli ta opcja nie jest dostępna, zainstaluj GNU find. Jeśli na komputerze Mac jest to możliwe dzięki pakietowi naparu findutils. Znajdź jest wtedy dostępne za pośrednictwem gfind.
DanCat,

regextype posix-egrep wykonało to za mnie zadanie. Myślę, że domyślnie jest to emacs wyrażenia regularnego.
zaatakował

35

Sądząc z innych odpowiedzi, wydaje się, że może to być wina znaleziska.

Możesz jednak zrobić to w ten sposób:

find . * | grep -P "[a-f0-9\-]{36}\.jpg"

Być może będziesz musiał trochę ulepszyć grep i użyć różnych opcji w zależności od tego, co chcesz, ale działa.


Działa dobrze dla mnie i zapewnia dużą swobodę w odniesieniu do wyrażenia regularnego.
glaucon

3
Minusem jest to, że z tego nie można skorzystać z find„s -prunefunkcjonalność, która będzie przeskoczyć pewnych katalogów całkowicie. Najczęściej nie jest to tak naprawdę ważne, ale warto o tym wspomnieć.
Alexander Bird

-Śliwka nadal będzie działać, tak myślę. Użycie -exec byłoby bardziej niebezpieczne - działałoby na wszystkich plikach, a nie tylko na tych, które grep pozwala na przekazywanie.
tpb261

13

w systemie Mac OS X (wyszukiwanie BSD) : Taki sam jak zaakceptowana odpowiedź, .*/prefiks jest potrzebny, aby dopasować pełną ścieżkę:

$ find -E . -regex ".*/[a-f0-9\-]{36}.jpg"

man findmówi -Ekorzysta z rozszerzonej obsługi wyrażeń regularnych


Wydaje -Esię, że nie jest dostępny na Ubuntu (testowany na WSL Ubuntu)
Warlike Chimpanzee

2
@Clever Little Monkey - Nie, zaakceptowana odpowiedź powinna działać na Ubuntu, ta odmiana dotyczy konkretnie Mac OS X (lub może innego wariantu BSD, takiego jak FreeBSD)
Stan Kurdziel

8

Spróbuj użyć pojedynczych cudzysłowów ('), aby uniknąć ucieczki powłoki z łańcucha. Pamiętaj, że wyrażenie musi pasować do całej ścieżki, tzn. Musi wyglądać następująco:

 find . -regex '\./[a-f0-9-]*.jpg'

Poza tym wydaje się, że moje znalezisko (GNU 4.4.2) zna tylko podstawowe wyrażenia regularne, a zwłaszcza składnię {36}. Myślę, że musisz się bez tego obejść.


8

Prosty sposób - możesz określić. * Na początku, ponieważ find pasuje do całej ścieżki.

$ find . -regextype egrep -regex '.*[a-f0-9\-]{36}\.jpg$'

znajdź wersję

$ find --version
find (GNU findutils) 4.6.0
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
<http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION 
FTS(FTS_CWDFD) CBO(level=2)

6

Podczas stosowania instrukcji find z wyrażeniem regularnym należy użyć bezwzględnej ścieżki do katalogu. W twoim przykładzie

find . -regex "[a-f0-9\-]\{36\}\.jpg"

należy zmienić na

find . -regex "./[a-f0-9\-]\{36\}\.jpg"

W większości systemów Linux niektóre dyscypliny wyrażenia regularnego nie mogą być rozpoznane przez ten system, więc musisz wyraźnie wskazać na wyrażenia regularne, takie jak

find . -regextype posix-extended -regex "[a-f0-9\-]\{36\}\.jpg"
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.