¿Cómo usar regex con el comando find?

298

Tengo algunas imágenes nombradas con la cadena uuid1 generada. Por ejemplo 81397018-b84a-11e0-9d2a-001b77dc0bed.jpg. Quiero encontrar todas estas imágenes usando el comando "buscar":

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

Pero no funciona. Algo mal con la expresión regular? ¿Podría alguien ayudarme con esto?

Thoslin
fuente
77
tal vez cambiar el tipo de expresión regular. El valor predeterminado es Emacs Regular Expressions , sea lo que sea que eso signifique.
Pavium

Respuestas:

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

Tenga en cuenta que debe especificar .*/al principio porque findcoincide con la ruta completa.

Ejemplo:

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

Mi versión 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
fuente
44
@ Tom es la forma en que la expresión regular en find funciona. De acuerdo con la página del manual, la expresión regular coincide con la ruta completa del archivo, incluidos los directorios, lo que significa que hay una "^ ... $"expresión implícita alrededor de la expresión regular. Debe coincidir con la línea de resultados ENTERA.
Manny D
2
No creo que necesite la /de .*/porque .*concuerda con cero o más de (casi) cualquier carácter.
Jeff
2
Para aquellos (como yo) que no leyeron la expresión regular correctamente la primera vez: tenga en cuenta las barras diagonales anteriores a los caracteres especiales de expresiones regulares, por ejemplo:\{36\}
Lucas Wilson-Richter
11
Tuve problemas para encontrar la lista completa de tipos de expresiones regulares (la página de manual no está actualizada):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
44
Asegúrese de poner la -regextypebandera antes de la -regexbandera, de lo contrario no se aplica.
Christopher Orr
84

La -regexexpresión de búsqueda coincide con el nombre completo , incluida la ruta relativa desde el directorio actual. Para find .esto siempre comienza con ./, luego cualquier directorio.

Además, estas son emacsexpresiones regulares, que tienen otras reglas de escape que las expresiones regulares egrep habituales.

Si todos estos están directamente en el directorio actual, entonces

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

Deberia trabajar. (No estoy realmente seguro, no puedo hacer que la repetición contada funcione aquí). Puede cambiar a expresiones egrep de la siguiente manera -regextype posix-egrep:

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

(Tenga en cuenta que todo lo que se dice aquí es para GNU find, no sé nada sobre el BSD, que también es el predeterminado en Mac).

Paŭlo Ebermann
fuente
1
Tenía paréntesis para múltiples cadenas coincidentes en mi expresión regular, por lo que el posix-egreptipo funcionó para mí.
palswim
2
Algo a tener en cuenta, -regextypees una opción para GNU findy no para BSD (al menos no como Mac BSD) find. Si esta opción no está disponible, asegúrese de instalar GNU find. Si en una Mac eso es posible con el paquete de café findutils. Buscar está entonces disponible a través de gfind.
DanCat
regextype posix-egrep hizo la tarea por mí. Creo que el valor predeterminado es regextype emacs.
Infoclogged
35

A juzgar por otras respuestas, parece que esto podría ser culpa de encontrar.

Sin embargo, puedes hacerlo de esta manera:

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

Puede que tenga que ajustar un poco el grep y usar diferentes opciones dependiendo de lo que desee, pero funciona.

Yarian
fuente
Me funcionó bien y proporciona un gran grado de libertad con respecto a la expresión regular.
glaucon
3
Una desventaja de esto es que no puede aprovechar findla -prunefuncionalidad de que omitirá ciertos directorios por completo. Muy a menudo esto no es realmente importante, pero vale la pena mencionarlo.
Alexander Bird
-prune todavía funcionará, supongo. Sería más peligroso usar -exec: se ejecutaría en todos los archivos y no solo en aquellos que grep permite pasar.
tpb261
13

en Mac OS X (BSD find) : igual que la respuesta aceptada, el .*/prefijo es necesario para que coincida con una ruta completa:

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

man finddice -Eutiliza soporte extendido regex

Stan Kurdziel
fuente
Parece -Eque no está disponible en Ubuntu (probado en WSL Ubuntu)
Warlike Chimpanzee
2
@Clever Little Monkey - No, la respuesta aceptada debería funcionar en Ubuntu, esta variación es específicamente para Mac OS X (o quizás otra variante BSD como FreeBSD)
Stan Kurdziel
8

Intente usar comillas simples (') para evitar que el shell se escape de su cadena. Recuerde que la expresión debe coincidir con la ruta completa, es decir, debe verse así:

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

Aparte de eso, parece que mi hallazgo (GNU 4.4.2) solo conoce expresiones regulares básicas, especialmente no la sintaxis {36}. Creo que tendrás que arreglártelas sin eso.

thiton
fuente
8

De manera simple: puede especificar. * Al principio porque find coincide con toda la ruta.

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

encontrar versión

$ 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
fuente
6

Debe usar la ruta absoluta del directorio al aplicar la instrucción de búsqueda con expresión regular. En su ejemplo, el

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

debe ser cambiado a

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

En la mayoría de los sistemas Linux, ese sistema no puede reconocer algunas disciplinas de expresión regular, por lo que debe señalar explícitamente -regexty como

find . -regextype posix-extended -regex "[a-f0-9\-]\{36\}\.jpg"
Encantador
fuente