Lista de archivos ordenados numéricamente

123

Tengo un montón de archivos de log1a log164.

Estoy tratando de LISTAR el directorio (ordenado) en un terminal UNIX, pero las funciones de clasificación solo proporcionan el formato de esta manera:

home:logs Home$ ls -1 | sort
log1.gz
log10.gz
log100.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz
...etc

Lo que quiero es

home:logs Home$ ls -1 | sort
log1.gz
log2.gz
log3.gz
log4.gz
log5.gz
log6.gz
log7.gz
...{more here}
log99.gz
log100.gz
log101.gz
log102.gz
...etc

¿Alguna sugerencia sobre lo que podría usar para hacer esto?

Volker Siegel
fuente
8
¡Esta es absolutamente una pregunta de programación, y no merece ser migrada solo porque la respuesta involucra el lenguaje de programación de bajo nivel!
tchrist
Si usted sabe de antemano que están nombrados log1.gza través log164.gz, entonces, ¿qué es lo que aún necesita ls -1de ellos para?
ruakh
1
@ruakh ls -1 muestra los resultados en una columna en lugar de a través
3
@Rabiani: Sé lo que ls -1hace: enumera los nombres de archivo. Como ya conocías los nombres de archivo, no entendí para qué lo necesitabas. Pero como has aceptado la respuesta de Kevin, ahora sé: no la necesitabas. Lo que tiene más sentido. :-)
ruakh

Respuestas:

40

bashLos frenos, {}los enumerarán en orden:

for file in log{1..164}.gz; do
    process "$file"
done
Kevin
fuente
267

¿Por qué no utilizar la lsfunción incorporada para este caso en particular?

-v natural sort of (version) numbers within text

Por ejemplo ls -1v log*

lik
fuente
Solución impresionante, aunque desearía que hubiera una solución igualmente simple usando sort, en caso de que uno tenga una serie de cadenas en lugar de un directorio de archivos
Hubro
23
En BSD / OS X esta opción es algo más: -v - Force unedited printing of non-graphic characters.
kenorb
Lamentablemente, la opción -v no está disponible en AIX (6.1)
bouvierr
66
Esta debería ser la mejor respuesta.
32r34wgf3e
1
para MacOS esto funcionará, no podría encontrar una opción como se mencionó, solols | sort -n
Ricky Levi
47

Con GNU ls (es decir, en Linux, Cygwin u otros sistemas que tienen GNU ls específicamente instalado):

ls -v

En zsh:

echo *(n)

En otras conchas:

echo log?.gz log??.gz log???.gz

Reemplace echopor printf '%s\n'si desea que cada nombre de archivo esté en una línea separada.

Si también desea metadatos de archivo ( ls -l) y no tiene GNU ls, deberá llamar lspor separado para cada nombre de archivo o grupo de nombres de archivo que desea ver en orden lexicográfico.

ls -ld log?.gz; ls -ld log??.gz; ls -ld log???.gz

Para evitar estas dificultades, use suficientes ceros a la izquierda en los nombres de sus archivos para que el tipo lexicográfico sea amigable para los humanos ( log001.gz, etc.).

Gilles
fuente
29

Si bien la solución ls -1ves ciertamente la mejor en este caso particular, creo que es bueno tener también una que funcione sortcomo en la pregunta original, ya que esto también funciona cuando su entrada no proviene ls. En este caso puedes usar:

ls -1 | sort -n -k1.4

La -nopción le dice a sort que clasifique numéricamente y -k 1.4establece la clave de clasificación en el primer campo (que es el nombre de archivo completo en este caso) comenzando desde el 4º carácter hasta el último.

Elmar Zander
fuente
En mi caso, ls -1 | sort -n -k1.4no funciona. Le da a los no clasificados al principio hasta 4 caracteres y luego los ordenados después del 4 ° carácter. En su ls -1 |sort | sort -n -k1.4lugar, utilicé y funcionó perfectamente.
Prabhu
3
@Prabhu, en cambio, podrías hacerlo sort -k1.1,1.3 -k1.4n. sortNo es necesario que las implementaciones sean estables, por lo que su enfoque no funcionará con todas las implementaciones. Vea también la -Vopción de GNU y FreeBSD sort.
Stéphane Chazelas
21

El GNU sort(como está disponible en Linux) tiene un modo de "clasificación de versiones" que interpreta los números dentro de números que no son números de la manera que usted solicita:

De man 1 sort:

    -V, --version-sort
           natural sort of (version) numbers within text

(Creación de archivos de prueba vacío a la lista:
touch log1.gz log2.gz log3.gz log99.gz log100.gz log101.gz log102.gz)

Su caso de ejemplo, agregando la -Vopción (o --version-sort):

ls -1 log*.gz | sort -V
log1.gz
log2.gz
log3.gz
log99.gz
log100.gz
log101.gz
log102.gz
Volker Siegel
fuente
6

si usa Mac o BSD intente esto:

ls -1 *.jpg | sort -n
Salvador Almaraz
fuente
3

Mi versión de Solaris no es compatible ls -v(grrr). Y la solución de clasificación proporcionada anteriormente 1) requiere el conocimiento de la posición de los dígitos en el nombre del archivo, y 2) no maneja cosas como números de versión de varias partes.

El siguiente enfoque es compatible con Solaris, no requiere conocimiento previo de las posiciones de los dígitos y maneja los números de versión con 2, 3 o 4 componentes (como: a-1.2, foo-5.6.7, bar_baz_9.10.11.12). También se usa sort -fpara plegar mayúsculas y minúsculas, y maneja correctamente directorios entremezclados con archivos:

ls -d | sort -f -t . -k 1,1 -k 2,2n -k 3,3n -k 4,4n

Tenga en cuenta que esta versión limita el primer componente a un solo dígito.

Si su sistema operativo objetivo es compatible ls -v, esa es claramente la solución superior.

MykennaC
fuente
1

Solución Perl:

ls log*.gz | perl -ne 'sub getnum{ $_[0] =~ /log(\d+)\.gz/; $1 }; push @A, $_; END{ print sort { getnum $a <=> $b } @A}'
Barton Chittenden
fuente
1
$ ls
log101.gz  log102.gz  log103.gz  log104.gz  log105.gz  log106.gz  log10.gz  log1.gz
$ ls | sort -t . -n -k1.4
log1.gz
log10.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz
kjohri
fuente
1
El -t .es superfluo aquí.
Stéphane Chazelas
0

Esto funcionó para mí.

Tengo archivos 1.jpg 2.jpg ... 18.jpg

$ echo *.jpg | tr -s ' ' '\n' | sort -n

sortse está confundiendo con la lssalida debido a los caracteres de color no imprimibles. Si intentas esto:

ls -1 --color=none *.jpg | sort -n

Funcionará perfectamente.

sortpuede ignorar los caracteres no imprimibles con la -iopción, pero todavía no funciona y no sé por qué.

Pero siempre puedes quitar un color como este y sortfuncionará:

ls -1 --color=always *.jpg | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | sort -n

Espero que algún día sorttenga una opción para esto.

cy8g3n
fuente