Comment utiliser regex avec la commande find?

298

J'ai quelques images nommées avec la chaîne uuid1 générée. Par exemple 81397018-b84a-11e0-9d2a-001b77dc0bed.jpg. Je veux découvrir toutes ces images en utilisant la commande "find":

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

Mais ça ne marche pas. Quelque chose ne va pas avec l'expression régulière? Quelqu'un pourrait-il m'aider avec ça?

thoslin
la source
7
peut-être changer le regextype. La valeur par défaut est Emacs Regular Expressions , quoi que cela signifie.
pavium

Réponses:

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

Notez que vous devez spécifier .*/au début car findcorrespond au chemin entier.

Exemple:

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

Ma version de 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
la source
4
@Tom, c'est la façon dont l'expression régulière dans la recherche fonctionne. Selon la page de manuel, l'expression régulière correspond à l'ensemble du chemin du fichier, répertoires inclus, ce qui signifie qu'il y a un implicite "^ ... $"entourant votre expression régulière. Il doit correspondre à la ligne de résultat ENTIER.
Manny D
2
Je ne pense pas que vous ayez besoin de l' /entrée .*/car .*correspond à zéro ou plus de (presque) n'importe quel caractère.
Jeff
2
Pour ceux (comme moi) qui n'ont pas lu correctement l'expression régulière la première fois: notez les barres obliques inverses précédant les caractères spéciaux d'expression régulière, par exemple:\{36\}
Lucas Wilson-Richter
11
J'ai eu du mal à trouver la liste complète des types de regex (la page de manuel n'est pas à jour):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
Assurez-vous de placer le -regextypedrapeau avant le -regexdrapeau, sinon il ne s'applique pas!
Christopher Orr
84

L' -regexexpression de recherche correspond au nom entier , y compris le chemin relatif du répertoire actuel. Pour find .cela commence toujours par ./, puis tous les répertoires.

De plus, ce sont emacsdes expressions régulières, qui ont d'autres règles d'échappement que les expressions régulières egrep habituelles.

Si ceux-ci sont tous directement dans le répertoire courant, alors

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

devrait marcher. (Je ne suis pas vraiment sûr - je ne peux pas faire fonctionner la répétition comptée ici.) Vous pouvez passer aux expressions egrep en -regextype posix-egrep:

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

(Notez que tout ce qui est dit ici est pour GNU find, je ne sais rien de celui de BSD qui est aussi le défaut sur Mac.)

Paŭlo Ebermann
la source
1
J'avais des parenthèses pour plusieurs chaînes correspondantes dans mon expression régulière, donc le posix-egreptype fonctionnait pour moi.
palswim
2
Quelque chose à noter, -regextypeest une option pour GNU findet non BSD (du moins pas comme Mac BSD) find. Si cette option n'est pas disponible, assurez-vous d'installer GNU find. Si sur un Mac, c'est possible avec le package de brassage findutils. La recherche est alors disponible via gfind.
DanCat
regextype posix-egrep a fait la tâche pour moi. Je pense que la valeur par défaut est emacs regextype.
infoclogged le
35

À en juger par d'autres réponses, il semble que ce soit la faute de la trouvaille.

Cependant, vous pouvez le faire de cette façon à la place:

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

Vous devrez peut-être modifier légèrement la grep et utiliser différentes options en fonction de ce que vous voulez, mais cela fonctionne.

yarian
la source
A bien fonctionné pour moi et offre une grande liberté par rapport à l'expression régulière.
glaucon
3
Un inconvénient avec ceci est que vous ne pouvez pas profiter de findde » -prunela fonctionnalité qui permet de sauter certains répertoires tout à fait. Le plus souvent, ce n'est pas vraiment important, mais cela vaut la peine d'être mentionné.
Alexander Bird
-le pruneau fonctionnera toujours, je suppose. Il serait plus dangereux d'utiliser -exec - il fonctionnerait sur tous les fichiers et pas seulement sur ceux que grep permet de passer.
tpb261
13

sur Mac OS X (recherche BSD) : Identique à la réponse acceptée, le .*/préfixe est nécessaire pour correspondre à un chemin complet:

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

man finddit -Eutilise un support regex étendu

Stan Kurdziel
la source
Semble -En'est pas disponible sur Ubuntu (testé sur WSL Ubuntu)
Warlike Chimpanzee
2
@Clever Little Monkey - Non, la réponse acceptée devrait fonctionner sur Ubuntu, cette variation est spécifiquement pour Mac OS X (ou peut-être une autre variante BSD comme FreeBSD)
Stan Kurdziel
8

Essayez d'utiliser des guillemets simples (') pour éviter l'échappement du shell de votre chaîne. N'oubliez pas que l'expression doit correspondre à l'ensemble du chemin, c'est-à-dire doit ressembler à:

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

En dehors de cela, il semble que ma recherche (GNU 4.4.2) ne connaisse que les expressions régulières de base, en particulier pas la syntaxe {36}. Je pense que vous devrez vous en passer.

thiton
la source
8

Manière simple - vous pouvez spécifier. * Au début car find correspond à tout le chemin.

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

trouver la version

$ 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
la source
6

Vous devez utiliser un chemin de répertoire absolu lors de l'application de l'instruction find avec une expression régulière. Dans votre exemple, le

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

devrait être changé en

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

Dans la plupart des systèmes Linux, certaines disciplines de l'expression régulière ne peuvent pas être reconnues par ce système, vous devez donc indiquer explicitement -regexty comme

find . -regextype posix-extended -regex "[a-f0-9\-]\{36\}\.jpg"
Charmant
la source