Cómo ordenar el tamaño legible por humanos

11

Básicamente busco archivos y luego los ordeno por tamaño. El script funciona si no clasifico el tamaño por legible por humanos. Pero quiero que el tamaño sea legible para los humanos. ¿Cómo puedo clasificar tamaños que sean legibles por humanos?

Por ejemplo:

 ls -l | sort -k 5 -n | awk '{print $9 " " $5}'

Esto funciona como se esperaba, obtuve el tamaño de mis archivos en bytes ascendentes:

1.txt 1
test.txt 3
bash.sh* 573
DocGeneration.txt 1131
andres_stuff.txt 1465
Branches.xlsx 15087
foo 23735
bar 60566
2016_stuff.pdf 996850

Ahora, quiero que el tamaño sea legible para humanos, así que agregué un parámetro -h a ls, y ahora algunos archivos están fuera de servicio:

 ls -lh | sort -k 5 -n | awk '{print $9 " " $5}'
1.txt 1
DocGeneration.txt 1.2K
andres_stuff.txt 1.5K
test.txt 3
Branches.xlsx 15K
foo 24K
bar 60K
bash.sh* 573
2016_stuff.pdf 974K

tvo000
fuente
-k 5- ¿Cómo funciona?
ctrl-alt-delor
@ ctrl-alt-delor: Creo que el tamaño se encuentra en la quinta columna de la lssalida
jesse_b
2
Usar en dulugar de lspodría ser una buena idea.
xenoid
... o find's -printfcon sus %py %sformateadores (seguido de una "humanización" de los tamaños).
Stephen Kitt
@Jesse_b mi error, simplemente asumí que los datos en la pregunta (marcados como esto es lo que obtuve) eran la entrada ordenada. Estaba equivocado.
ctrl-alt-delor

Respuestas:

28

Tratar sort -h k2

-h, --human-numeric-sort compara números legibles por humanos (por ejemplo, 2K 1G)

Es parte de gnu sort, BSD sort y otros.

ctrl-alt-delor
fuente
55
¿No se debe evitar analizar la salida de ls?
3
@Tomasz No siempre. Si proporciona el resultado que necesita, canalizarlo a otra operación de formateo no es particularmente peligroso. Lo que no debe hacer es recorrer la salida de ls, y en su lugar usar el globing de archivos directamente. Globbing solo no funcionará aquí. Dicho esto, probablemente preferiría duesto.
Bloodgain
1
@Bloodgain no garantiza que el formato ls sea el mismo en todos los sistemas / binarios ls, por lo que analizarlo de forma portátil se considera imposible.
D. Ben Knoble
1
Además, los nombres de archivo con espacios en blanco serán destrozar cosas
D. Ben Knoble
1
@Bloodgain: files=(); for f in *; do [[ -L "$f" ]] && files+=("$f"); done; echo ${#files[@]}(podría tener el cambio de prueba de enlace simbólico incorrecto). Si no te interesan los enlaces simbólicos, files=(*); echo ${#files[@]}que se vuelven portátiles si los usas sety no las matrices.
D. Ben Knoble
29

lstiene esta funcionalidad incorporada, use la -Sopción y ordene en orden inverso:ls -lShr

       -r, --reverse
              reverse order while sorting

       -S     sort by file size, largest first
Mark McKinstry
fuente
1
-hno es una opción estándarls , pero debe ser utilizable si OP ya lo tiene. El resto son estándar, y ciertamente es la respuesta que habría escrito.
Toby Speight
55
+1 No pierdas el tiempo analizando la salida de ls.
David Richerby
Esta es la mejor respuesta, pero debe incluir la información en el comentario de @ Toby: -Spodría no estar disponible para usted ls. FWIW, -Ses compatible incluso con la biblioteca de Emacs ls-lisp.el, que se utiliza cuando el sistema operativo no tiene ls. Funciona en Emacs en MS Windows, por ejemplo.
Dibujó el
Esta debería ser la respuesta aceptada.
dispersión
1
@Drew: el comentario de Toby dice que -hpuede no estar disponible universalmente, pero OP ya lo está utilizando de todos modos. -Srealmente debería estar universalmente disponible, porque está en el enlace POSIX que proporciona Toby. Sin embargo, existen bastantes kits de herramientas que no son POSIX.
Kevin
5

Como no se mencionó ningún shell específico, aquí se explica cómo hacer todo en el zshshell:

ls -lhf **/*(.Lk-1024oL)

El **patrón global coincide como *pero a través /de los nombres de ruta, es decir, como lo haría una búsqueda recursiva.

El lscomando habilitaría tamaños legibles por humanos con -h, y formato de salida de lista larga con -l. La -fopción deshabilita la clasificación, por lslo que solo enumeraría los archivos en el orden en que se proporcionan.

Este orden está organizado por el **/*(.Lk-1024oL)patrón global de nombre de archivo para que los archivos más pequeños se enumeren primero. El **/*bit coincide con cada archivo y directorio en este directorio y debajo, pero (...)modifica el comportamiento del glob (es un "calificador glob").

Es oLal final que ordena ( o) los nombres por tamaño de archivo ( L, "longitud").

Al .principio, el globo solo coincide con los archivos normales (sin directorios).

El Lk-1024bit selecciona archivos cuyo tamaño es inferior a 1024 KB ("longitud en KB inferior a 1024").

Si zshno es su shell interactivo principal, entonces podría usar

zsh -c 'ls -lf **/*(.Lk-1024oL)'

Use setopt GLOB_DOTS(o zsh -o GLOB_DOTS -c ...) para también hacer coincidir nombres ocultos. ... o simplemente agregue Da la cadena de calificación global.


Ampliando lo anterior, suponiendo que desea una salida de 2 columnas con nombres de ruta y tamaños legibles por humanos, y también suponiendo que tiene numfmtde GNU coreutils,

zmodload -F zsh/stat b:zstat

for pathname in **/*(.Lk-1024oL); do
    printf '%s\t%s\n' "$pathname" "$(zstat +size "$pathname" | numfmt --to=iec)"
done

o más rápido

paste <( printf '%s\n' **/*(.Lk-1024oL) ) \
      <( zstat -N +size **/*(.Lk-1024oL) | numfmt --to=iec )
Kusalananda
fuente
4

Si sortno tiene la -hopción, puede usar un comando awk (aunque muy largo) como el siguiente:

find . -type f -size -1024k -exec ls -al {} \; | sort -k 5 -n | awk '{if ($5 > 1099511627776) {print $9,$5/1024/1024/1024/1024"T"} else if ($5 > 1073741824) {print $9,$5/1024/1024/1024"G"} else if ($5 > 1048576) {print $9,$5/1024/1024"M"} else if ($5 > 1024) {print $9,$5/1024"K"} else {print $9,$5"B"}}' | column -t

Esto ordenará su salida en bytes y luego los convertirá a su tamaño legible por humanos.

jesse_b
fuente
-1

¿Funcionaría esto?

ls -l | awk '{if ($5<=1024) {print}}' | sort -k 5 -n | awk '{print $9"\t"substr($5/1024,1,3)"k"} '| column -t

La primera awkexp buscará los archivos de menos de 1M y la segunda tomará el tamaño del byte del resultado y lo convertirá a KB e imprimirá los primeros 3 elementos para obtener un tamaño legible por humanos.

Vignesh SP
fuente
Eso realmente no resuelve la pregunta de OP: solo se ve en el directorio actual y solo imprimirá archivos normales. También se comparará con 1Kb en lugar de 1MB. Finalmente buscamos respuestas con alguna explicación sobre por qué funciona el código.
grochmal
Mi mal agregó lo que hace.
Vignesh SP