Intervalos de arquivos com vários dígitos em ordem lexicográfica no zsh

24

Eu gostaria de especificar um intervalo de arquivos (em ordem lexicográfica) com dois números inteiros (por exemplo, 2 a 57) no zsh por meio de globbing.

Por exemplo: "escolha os arquivos de 2 a 57 em ordem lexicográfica no caminho que corresponda a algum padrão de globbing".

Eu pensei que usando colchetes faria isso

 for x in /foo/bar/*[2-57]; do print $x; done

mas zsh aparentemente pensa que eu estou pedindo para os arquivos 2para 5(ou algo parecido) em vez de arquivos 2para 57. Alguma idéia do porquê? Como posso fazer isso?

Amelio Vazquez-Reina
fonte

Respostas:

30

[2-57]é um conjunto de caracteres consistindo de 2, 3, 4, 5e 7, em zsh e qualquer outro wildcard e sintaxe regexp lá fora. Seu padrão glob *[2-57]corresponde a todos os nomes de arquivos cujo último caractere é um desses cinco dígitos.

Eu acho que você está se lembrando mal da sintaxe do [m,n] qualificador glob . Os qualificadores de globos sempre aparecem entre parênteses no final do padrão, e o separador de intervalo é uma vírgula. O padrão se *([2,57])expande para a 2ª, 3ª,…, 57ª correspondências. A ordem de expansão padrão é lexicográfica (com alguma mágica especial para classificar números em ordem numérica, se a numeric_glob_sortopção estiver configurada); você pode controlá-lo com o qualificador oou Oglob (por exemplo, *(om[2,57])para corresponder ao 57 arquivo mais recente, exceto o arquivo mais recente).

for x in /foo/bar/*([2,57]); do print $x; done

Não o que você pediu, mas relacionado e possivelmente útil para futuros leitores: se você quiser enumerar os arquivos 2 a 57, se eles existem ou não, é possível usar uma expressão de intervalo entre chaves . Esse recurso também existe no bash e no ksh.

echo hello{2..57}

E se você deseja combinar arquivos cujo nome contém um número entre 2 e 57, você pode usar o padrão <2-57>. Isso é específico para o zsh.

$ ls
file1 file2 file3 file57 file58
$ echo file<2-57>
file2 file3 file57

Observe que um padrão como *<2-57>provavelmente não faz o que você espera, porque também *pode corresponder a dígitos. Por exemplo, file58corresponde *<2-57>, com a file5correspondência da *parte e 8a <2-57>parte. O padrão *[^0-9]<2-57>evita esse problema.

Gilles 'SO- parar de ser mau'
fonte
Você está certo. Eu estava me lembrando do qualificador da glob. Obrigado pela explicação cuidadosa.
Amelio Vazquez-Reina
By the way, esta declaração me deixou um pouco confuso: if you want to enumerate files 2 to 57 whether they exist or not, you can use a range brace expression. Se os arquivos não existirem e não houver correspondências, como a expansão de chaves saberia como expandir? (como seria expandir de forma diferente do qualificador glob?)
Amelio Vazquez-Reina
2
@intrpc foo{8..11}barexpande para foo8bar foo9bar foo10bar foo11bar. Esse pouco de expansão não está relacionado aos nomes dos arquivos. Da mesma forma, foo{eight,nine,ten,eleven}barexpande para fooeightbar fooninebar footenbar fooelevenbar. Isso é expansão de chaves em ksh / bash / zsh.
Gilles 'SO- stop be evil'
6

mas o zsh aparentemente pensa que estou pedindo os arquivos 2 a 5 (ou algo parecido) em vez dos arquivos 2 a 57. Alguma idéia do porquê?

Como []colchetes indicam uma lista de caracteres correspondentes (que podem ser dígitos), não números interpretados matematicamente. Esse padrão é comparado com um único caractere. A lista pode conter intervalos, mas de dígitos ou letras. [2-57]A correspondência se expande para "Todos os dígitos no intervalo de 2 a 5 e 7" .

Para corresponder números de 2 a 57, seria mais fácil usar uma expressão de sequência em vez de um padrão de globbing (ou junto com isso):

for x in /foo/bar/*{2..57}; do print $x; done

Edit : Mas isso, infelizmente, não fornecerá a ordem lexicográfica de todos os arquivos listados - eles serão agrupados por terminações de números comuns devido à expansão do shell.

rozcietrzewiacz
fonte
Obrigado @rozcietrzewiacz! Eu deveria ter pensado nisso. Meus arquivos tinham números neles, então, por um momento eu pensei que []estava imprimindo as coisas em ordem ..
Amelio Vazquez-Reina
Sua explicação [2-57]está correta, mas eu não acho {2..57}(é isso que você quis dizer, certo?) É relevante para o que a intrpc deseja fazer, que é "escolher os arquivos de 2 a 57 em ordem lexicográfica".
Gilles 'SO- stop be evil'
Obrigado pela edição (hora de dormir, eu acho). E você está certo - eu tinha esquecido a parte da ordem lexicográfica .
rozcietrzewiacz