Wie verwende ich Regex mit dem Befehl find?

297

Ich habe einige Bilder mit der generierten Zeichenfolge uuid1 benannt. Zum Beispiel 81397018-b84a-11e0-9d2a-001b77dc0bed.jpg. Ich möchte alle diese Bilder mit dem Befehl "find" herausfinden:

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

Aber es funktioniert nicht. Stimmt etwas mit der Regex nicht? Könnte mir jemand dabei helfen?

Thoslin
quelle
7
Vielleicht ändern Sie den regulären Texttyp. Die Standardeinstellung ist Emacs Regular Expressions , was auch immer das bedeutet.
Pavium

Antworten:

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

Beachten Sie, dass Sie .*/am Anfang angeben müssen, da dies finddem gesamten Pfad entspricht.

Beispiel:

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

Meine Version von 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'.
Susam Pal
quelle
4
@ Tom es ist die Art und Weise, wie Regex in Find funktioniert. Laut der Manpage stimmt der reguläre Ausdruck mit dem gesamten Dateipfad überein, einschließlich der Verzeichnisse. Dies bedeutet, dass "^ ... $"Ihr regulärer Ausdruck implizit ist . Es muss mit der GANZEN Ergebnislinie übereinstimmen.
Manny D
2
Ich glaube nicht, dass du das /in brauchst, .*/weil es .*mit null oder mehr von (fast) jedem Charakter übereinstimmt.
Jeff
2
Für diejenigen (wie ich), die den regulären Ausdruck beim ersten Mal nicht richtig gelesen haben: Beachten Sie die Backslashes vor den regulären regulären Ausdruckszeichen, z. B.:\{36\}
Lucas Wilson-Richter
11
Ich hatte Probleme, die vollständige Liste der Regex-Typen zu finden (Manpage ist nicht aktuell):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
Stellen Sie sicher, dass die -regextypeFlagge vor der -regexFlagge steht, da sie sonst nicht gilt!
Christopher Orr
84

Der -regexSuchausdruck entspricht dem gesamten Namen , einschließlich des relativen Pfads aus dem aktuellen Verzeichnis. Denn find .das beginnt immer mit ./dann Verzeichnissen.

Dies sind auch emacsreguläre Ausdrücke, für die andere Regeln gelten als für die üblichen egrep-regulären Ausdrücke.

Wenn sich diese alle direkt im aktuellen Verzeichnis befinden, dann

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

sollte arbeiten. (Ich bin mir nicht sicher - ich kann die gezählte Wiederholung hier nicht zum Laufen bringen.) Sie können zu egrep-Ausdrücken wechseln, indem Sie -regextype posix-egrep:

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

(Beachten Sie, dass alles, was hier gesagt wird, für GNU-Fund ist. Ich weiß nichts über das BSD, das auch auf dem Mac Standard ist.)

Paŭlo Ebermann
quelle
1
Ich hatte Klammern für mehrere übereinstimmende Zeichenfolgen in meinem regulären Ausdruck, daher posix-egrepfunktionierte der Typ für mich.
Palswim
2
Zu beachten -regextypeist eine Option für GNU findund nicht für BSD (zumindest nicht für Mac BSD) find. Wenn diese Option nicht verfügbar ist, müssen Sie GNU find installieren. Wenn auf einem Mac, ist das mit dem Brühpaket möglich findutils. Find ist dann über verfügbar gfind.
DanCat
Der Regextyp posix-egrep hat die Aufgabe für mich erledigt. Ich denke, die Standardeinstellung ist Regextype Emacs.
Infoclogged
35

Nach anderen Antworten zu urteilen, scheint dies die Schuld von find zu sein.

Sie können dies jedoch stattdessen folgendermaßen tun:

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

Möglicherweise müssen Sie den Grep ein wenig optimieren und verschiedene Optionen verwenden, je nachdem, was Sie möchten, aber es funktioniert.

Yarian
quelle
Hat für mich gut funktioniert und bietet ein hohes Maß an Freiheit in Bezug auf die Regex.
Glaukon
3
Ein Nachteil dabei ist , dass Sie nicht nutzen können find‚s - -pruneFunktionalität , die ganz bestimmte Verzeichnisse überspringen. Meistens ist das nicht wirklich wichtig, aber es ist erwähnenswert.
Alexander Bird
-prune wird immer noch funktionieren, denke ich. Es wäre gefährlicher, -exec zu verwenden - es würde auf allen Dateien ausgeführt und nicht nur auf denen, die grep passieren lässt.
tpb261
13

unter Mac OS X (BSD-Suche) : Wie bei der akzeptierten Antwort wird das .*/Präfix benötigt, um einem vollständigen Pfad zu entsprechen:

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

man findsagt -Everwendet erweiterte Regex-Unterstützung

Stan Kurdziel
quelle
Scheint -Enicht verfügbar auf Ubuntu (getestet auf WSL Ubuntu)
Warlike Chimpanzee
2
@Clever Little Monkey - Nein, die akzeptierte Antwort sollte unter Ubuntu funktionieren. Diese Variante ist speziell für Mac OS X (oder vielleicht eine andere BSD-Variante wie FreeBSD)
Stan Kurdziel
8

Versuchen Sie, einfache Anführungszeichen (') zu verwenden, um zu vermeiden, dass die Shell aus Ihrem String entweicht. Denken Sie daran, dass der Ausdruck mit dem gesamten Pfad übereinstimmen muss, dh wie folgt aussehen muss:

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

Abgesehen davon scheint mein Fund (GNU 4.4.2) nur grundlegende reguläre Ausdrücke zu kennen, insbesondere nicht die {36} -Syntax. Ich denke, du musst ohne auskommen.

Thiton
quelle
8

Einfacher Weg - Sie können. * Am Anfang angeben, da find mit dem gesamten Pfad übereinstimmt.

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

Version finden

$ 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)
binbjz
quelle
6

Sie sollten den absoluten Verzeichnispfad verwenden, wenn Sie eine Suchanweisung mit regulären Ausdrücken anwenden. In Ihrem Beispiel ist die

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

sollte geändert werden in

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

In den meisten Linux-Systemen können einige Disziplinen im regulären Ausdruck von diesem System nicht erkannt werden, daher müssen Sie explizit auf -regexty like hinweisen

find . -regextype posix-extended -regex "[a-f0-9\-]\{36\}\.jpg"
Schön
quelle