Rangos de archivos de varios dígitos en orden lexicográfico en zsh

24

Me gustaría especificar un rango de archivos (en orden lexicográfico) con dos enteros (por ejemplo, 2 a 57) en zsh haciendo globbing.

Por ejemplo: "seleccione los archivos del 2 al 57 en orden lexicográfico debajo de la ruta que coincida con algún patrón global".

Pensé que usar corchetes lo haría

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

pero zsh al parecer piensa que estoy pidiendo los archivos 2a 5(o algo por el estilo) en lugar de archivos 2a 57. ¿Alguna idea de por qué? ¿Cómo puedo lograr esto?

Amelio Vazquez-Reina
fuente

Respuestas:

30

[2-57]es un conjunto de caracteres que consiste en 2, 3, 4, 5y 7, en zsh y cualquier otro comodín y la sintaxis de expresiones regulares que hay. Su patrón global *[2-57]coincide con cada nombre de archivo cuyo último carácter es uno de esos cinco dígitos.

Creo que no recuerda la sintaxis del [m,n] calificador global . Los calificadores Glob siempre van entre paréntesis al final del patrón, y el separador de rango es una coma. El patrón se *([2,57])expande al 2º, 3º,…, 57º partido. El orden de expansión predeterminado es lexicográfico (con algo de magia especial para ordenar los números en orden numérico si la numeric_glob_sortopción está configurada); puede controlarlo con el calificador oo Oglob (por ejemplo, *(om[2,57])para que coincida con el 57 archivo más reciente, excepto el archivo más reciente).

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

No es lo que solicitó, sino relacionado y posiblemente útil para futuros lectores: si desea enumerar los archivos 2 a 57, ya sea que existan o no, puede usar una expresión de llaves de rango . Esta característica también existe en bash y ksh.

echo hello{2..57}

Y si desea hacer coincidir archivos cuyo nombre contiene un número entre 2 y 57, puede usar el patrón <2-57>. Esto es específico de zsh.

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

Tenga en cuenta que *<2-57>es probable que un patrón como no haga lo que espera, porque también *podría coincidir con los dígitos. Por ejemplo, file58coincide *<2-57>, con la file5coincidencia de la *parte y la 8coincidencia de la <2-57>parte. El patrón *[^0-9]<2-57>evita este problema.

Gilles 'SO- deja de ser malvado'
fuente
Tienes razón. Estaba recordando mal el calificador global. Gracias por la cuidadosa explicación.
Amelio Vazquez-Reina
Por cierto, esta afirmación me tiene un poco confundido: if you want to enumerate files 2 to 57 whether they exist or not, you can use a range brace expression. Si los archivos no existen y no hay coincidencias, ¿cómo podría la expansión de llaves saber cómo expandirse? (¿cómo se expandiría de manera diferente al calificador global?)
Amelio Vazquez-Reina
2
@intrpc se foo{8..11}barexpande a foo8bar foo9bar foo10bar foo11bar. Este bit de expansión no está relacionado con los nombres de archivo. Del mismo modo, se foo{eight,nine,ten,eleven}barexpande a fooeightbar fooninebar footenbar fooelevenbar. Esta es la expansión de llaves en ksh / bash / zsh.
Gilles 'SO- deja de ser malvado'
6

pero zsh aparentemente cree que estoy pidiendo los archivos 2 a 5 (o algo así) en lugar de los archivos 2 a 57. ¿Alguna idea de por qué?

Debido a que los []corchetes indican una lista de caracteres coincidentes (que pueden ser dígitos), no números interpretados matemáticamente. Tal patrón se compara con un solo personaje. La lista puede contener rangos, pero de dígitos o letras. [2-57]la coincidencia se expande a "Todos los dígitos en el rango de 2 a 5 y un 7" .

Para hacer coincidir los números del 2 al 57, sería más fácil usar una expresión de secuencia en lugar de un patrón global (o junto con tal):

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

Editar : Pero esto, desafortunadamente, no le dará un orden lexicográfico de todos los archivos enumerados; se agruparán por terminaciones de números comunes debido a la expansión de la shell.

rozcietrzewiacz
fuente
Gracias @rozcietrzewiacz! Debería haber pensado en eso. Mis archivos tenían números, así que por un momento pensé que []estaba imprimiendo las cosas en orden ...
Amelio Vazquez-Reina
Su explicación de [2-57]es correcta, pero no creo {2..57}(eso es lo que quiso decir, ¿verdad?) Es relevante para lo que intrpc quiere hacer, que es "elegir los archivos 2 a 57 en orden lexicográfico".
Gilles 'SO- deja de ser malvado'
Gracias por la edición (hora de ir a dormir, supongo). Y tienes razón: me había olvidado de la parte del orden lexicográfico .
rozcietrzewiacz