Tengo un comando de búsqueda y me gustaría emitirlo desde un directorio arbitrario con una $directory
variable en lugar del punto .
para el directorio de trabajo actual.
lo que funciona es esto
- Ejemplo 1
find $directory -maxdepth 1 -type d -name "test*"
Eso me da algunos resultados.
También esto funciona
- Ejemplo 2
find . -maxdepth 1 -type d -regextype posix-extended -regex "^./[a-zA-Z0-9]+([-_]?[a-zA-Z0-9]+)*-[0-9]{1,3}(.[0-9]{1,3}){,3}\$"
Sin embargo, con $directory
a no funciona. Tenga en cuenta que eliminé el ./
al comienzo de la expresión regular.
- Ejemplo 3
find $directory -maxdepth 1 -type d -regextype posix-extended -regex "^[a-zA-Z0-9]+([-_]?[a-zA-Z0-9]+)*-[0-9]{1,3}(.[0-9]{1,3}){,3}\$"
¿Por qué es así?
Gracias
Respuesta1
-regex
(no estándar), al igual que las -path
coincidencias estándar en la ruta completa de los archivos. Esas rutas comienzan con el contenido de $directory
seguido de los directorios y archivos encontrados por find
. Entonces, si $directory
es /some/dir
, -regex
coincidirá con la expresión regular /some/dir/file-discovered-by-find
y nunca coincidirá aquí, ya que el primer carácter es un /
, no un alnum.
En el primer caso, su expresión regular comenzó con ^./
(debería haber sido ^\./
como .
es un operador de expresión regular, o simplemente \./
como ^
está implícito en GNU find
) -regex
como $directory
estaba .
.
Tendrías que hacer algo similar con $directory
, teniendo en cuenta que todos los operadores de expresiones regulares en $directory
( ^$*()+[]?.\
...) deberían tener escape. Pero aquí también podrías hacerlo:
find "$directory" -maxdepth 1 -type d -regextype posix-extended \
-regex '.*/[[:alnum:]]+([-_][[:alnum:]]+)*-[[:digit:]]{1,3}(\.[[:digit:]]{1,3}){0,3}'
(También lo reemplacé .
con, \.
ya que sospecho que desea hacer coincidir un carácter literal .
y no cualquier carácter, y eliminé el ?
que no era necesario aquí).
Es decir, haga que su patrón (que aquí se garantiza que no abarcará un /
) coincida después de cualquier /
(y hasta el final de la ruta del archivo, como $
también está implícito) en lugar de después de algo que coincida $directory
.
Con zsh -o extendglob
, puedes hacer:
set -o extendedglob
w=[0-9a-zA-Z] d=[0-9]
print -rC1 -- $directory/$~w##([-_]$~w##)#-$~d(#c1,3)(.$~d(#c1,3))(#c0,3)(#q/)
El cual tiene varias ventajas sobre el de GNU find
:
- Funcionaría incluso en sistemas que no sean GNU (elimina la dependencia de GNU
find
) - funciona incluso si
$directory
comienza con-
- te da una lista ordenada
- en
zsh
, lo que[a-zA-Z0-9]
coincide no es aleatorio y no varía con las configuraciones regionales como enfind
y coincide con los caracteres. Supongo que desea que coincidan y solo ellos. Enfind
, necesitarías[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]
obtener el equivalente. - Funciona incluso si
$directory
es un enlace simbólico a un directorio (aunque puedes agregar la-H
opciónfind
para eso). - Funciona incluso si las rutas de archivo (en este caso, el contenido de
$directory
) contienen una secuencia de bytes que no forman caracteres válidos en la configuración regional actual (find
's-regex
'.*
no pueden coincidir con ellos porque.
solo coincide con caracteres válidos). - en lugar de imprimir esa lista, puede usarla directamente (como argumentos para un comando, para recorrerlo, etc.)
- También puede usar cosas como
(<0-255>~????*)
hacer coincidir números decimales del 0 al 255 compuestos por no más de 3 dígitos o(<0-255>~0?*)
para aquellos números sin 0 inicial,zsh
siendo los globos una de las pocas API de coincidencia de patrones que admiten rangos de números coincidentes.