como encontrar arquivos com base no intervalo de nome de arquivo?

2

Eu tenho alguns arquivos com nomes numéricos: 2341a.po , 4567211someword.po , 0012.po , etc. Eu gostaria de encontrar um conjunto de arquivos com base no intervalo numérico. como [126 - 363] .

Normalmente, uso expressões regulares com find . Qualquer intervalo numérico [N, M] pode ser composto por duas expressões regulares larger than N e less than M .

O maior que N:

Se N = vxyz , eu primeiro faço uma correspondência para todos os value > V000, (V=v+1) com [V-9]\d{3,}

Em seguida, corresponda vX00 , X=x+1 , com v[X-9]\d\d

Em seguida, corresponda vxY0 , Y=y+1 , com vx[Y-9]\d

e último vxy[z-9]

Exemplo:

Para corresponder a number>=234 , eu uso:

'^(0*([3-9]\d{2,}|2[4-9]\d|23[4-9]))'

O menor que M:

Com base em lógica semelhante, teremos:

^(0*(vxy[0-z]|vx[0-Y]\d|v[0-X]\d\d|[1-V]\d\d|\d{1,3}))[^0-9]

com Y=y-1,X=x-1,V=v-1

Por exemplo, o comando follow encontrará qualquer arquivo entre [253, 326]:

find . -maxdepth 1 -type f -regextype posix-extended -iregex '^\./0*([3-9][0-9]{2,}|2[6-9][0-9]{2,}|25[3-9]).*' -iregex '^\./0*(32[0-6]|3[0-1][0-9]|[0-2][0-9][0-9]|[0-9]{1,2})[^0-9].*'

No entanto, esse método é muito chato para lidar com números longos. Existe alguma maneira melhor e mais fácil de fazer isso?

    
por Wang 26.12.2014 / 01:40

4 respostas

2

com zsh :

setopt extendedglob # best in ~/.zshrc
ls -ld -- <126-253>(*.po~[0-9]*)

Recursivamente, incluindo em diretórios ocultos e somente arquivos regulares:

ls -ld -- **/<126-253>(*.po~[0-9]*)(D.)

use zargs se você encontrar o erro arg list too long .

    
por 26.12.2014 / 12:16
1

Você pode gerar uma lista de arquivos com os números que deseja encontrar e colocá-los na lista de argumentos para find usando xargs . Por exemplo, usando bash , o equivalente a usar -maxdepth 1 como na pergunta seria:

echo {253..326} | xargs sh -c 'find "$@" -type f -maxdepth 0' sh

Observe que você pode usar a opção -I para xargs (ou seja, xargs -I{} find {} -type f ), mas o GNU xargs força -L 1 com essa opção, o que significa que um processo de localização separado é iniciado para cada argumento. Usar sh contorna esse problema.

Para uma profundidade arbitrária, você pode fazer:

printf -- '-o -name %d ' {254..326} |
  xargs -n 3000 sh -c 'find -type f \( -name 253 "$@" \)' sh

O argumento -n (número máximo de argumentos adicionados por comando) deve ser escolhido para limitar o tamanho da lista de argumentos xargs constructos. Se for muito grande, o limite pode ser alcançado devido ao tamanho geral da lista de argumentos, em vez do número de argumentos. Deve ser um múltiplo de 3 para que você não fique com um -o ou -name na lista.

    
por 26.12.2014 / 11:46
0

Uma extensão de força bruta na resposta de Graeme:

find . -type f -regextype posix-awk -regex ".*/0*($(seq -s'|' 254 456)).*" 

Você pode usar \| em vez de | e \(\) em vez de () se precisar de POSIX (mas, seq não é POSIX, é?).

$ find . -maxdepth 2 -type f -regextype posix-awk -regex ".*/0*($(seq -s'|' 254 456)).*"    
./.fontconfig/3047814df9a2f067bd2d96a2b9c36e5a-le32d4.cache-3
./.fontconfig/3830d5c3ddfd5cd38a049b759396e72e-le32d4.cache-3
./.fontconfig/385c0604a188198f04d133e54aba7fe7-le32d4.cache-3
./Documents/374620-63301.pdf
./4567211someword.po

Hmm. Parece que devemos adicionar um caractere não-dígito para marcar o final do número. Talvez ".*/0*($(seq -s'|' 254 456))[^0-9].*" ?

    
por 26.12.2014 / 12:01
0
find | perl -ne 'print if(m!^\./(\d+)! and $1 > 126 and $1 <363)'

... possivelmente adicionando algumas das boas ideias apresentadas nas outras respostas.

O Regex pode precisar de algum ajuste (por exemplo: ^\./(\d+)\w*.po$ )

    
por 31.12.2014 / 16:40