Eu tenho um comando find e gostaria de emiti-lo a partir de um diretório arbitrário com uma $directory
variável no lugar do ponto .
do diretório de trabalho atual.
O que funciona é isso
- Exemplo 1
find $directory -maxdepth 1 -type d -name "test*"
Isso me dá alguns resultados.
Também isso funciona
- Exemplo 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}\$"
No entanto, com a $directory
isso não funciona. Lembre-se de que removi o ./
no início do regex.
- Exemplo 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 que?
Obrigado
Responder1
-regex
(não padrão), como o padrão -path
corresponde ao caminho completo dos arquivos. Esses caminhos começam com o conteúdo de $directory
seguido pelos diretórios e arquivos encontrados por find
. Portanto, se $directory
for /some/dir
, -regex
corresponderá ao regex /some/dir/file-discovered-by-find
e nunca corresponderá aqui, pois o primeiro caractere é a /
, não um alnum.
No primeiro caso, seu regexp começou com ^./
(deveria ter sido ^\./
um .
operador regexp, ou apenas \./
como ^
está implícito no GNU find
) -regex
como $directory
havia .
.
Você precisaria fazer algo semelhante com $directory
, tendo em mente que todos os operadores regexp em $directory
( ^$*()+[]?.\
...) precisariam ser escapados. Mas aqui você também pode fazer:
find "$directory" -maxdepth 1 -type d -regextype posix-extended \
-regex '.*/[[:alnum:]]+([-_][[:alnum:]]+)*-[[:digit:]]{1,3}(\.[[:digit:]]{1,3}){0,3}'
(Também substituí .
por, \.
pois suspeito que você deseja corresponder a um literal .
e não a qualquer caractere, e removi o ?
que não era necessário aqui).
Ou seja, faça com que seu padrão (que aqui é garantido que não abrange um /
) corresponda após any /
(e até o final do caminho do arquivo, como $
também está implícito) em vez de depois de algo que corresponda a $directory
.
Com zsh -o extendglob
você pode fazer:
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/)
Que tem várias vantagens sobre o GNU find
:
- funcionaria mesmo em sistemas não-GNU (remove a dependência do GNU
find
) - funciona mesmo se
$directory
começar com-
- fornece uma lista ordenada
- in
zsh
, o que[a-zA-Z0-9]
corresponde não é aleatório e não varia com as localidades como infind
e corresponde aos caracteres que suponho que você deseja corresponder e somente eles. Emfind
, você precisaria[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]
obter o equivalente. - funciona mesmo que
$directory
seja um link simbólico para um diretório (você pode adicionar a-H
opçãofind
para isso). - funciona mesmo se os caminhos do arquivo (neste caso, o conteúdo de
$directory
) contiverem uma sequência de bytes que não formam caracteres válidos no código do idioma atual (find
os 's-regex
'.*
não puderam corresponder àqueles, pois.
correspondem apenas a caracteres válidos). - em vez de imprimir essa lista, você pode usá-la diretamente (como argumentos para um comando, para fazer um loop sobre ela, etc.)
- você também pode usar coisas como
(<0-255>~????*)
combinar números decimais de 0 a 255 compostos de no máximo 3 dígitos ou(<0-255>~0?*)
para aqueles números sem 0 inicial,zsh
sendo globs uma das poucas APIs de correspondência de padrões que suportam intervalos de correspondência de números.