it-swarm-es.com

¿Cómo puedo ordenar la salida du -h por tamaño?

Necesito obtener una lista de lectura humana de salida.

Sin embargo, du no tiene una opción de "ordenar por tamaño", y la canalización a sort no funciona con el indicador legible por humanos.

Por ejemplo, ejecutando:

du | sort -n -r 

Emite un uso de disco ordenado por tamaño (descendente):

du |sort -n -r
65108   .
61508   ./dir3
2056    ./dir4
1032    ./dir1
508     ./dir2

Sin embargo, ejecutarlo con el indicador legible por humanos no se ordena correctamente:

du -h | sort -n -r

508K    ./dir2
64M     .
61M     ./dir3
2.1M    ./dir4
1.1M    ./dir1

¿Alguien sabe de una manera de ordenar du -h ¿por tamaño?

1029
Tom Feiner

A partir de GNU coreutils 7.5 lanzado en agosto de 2009, sort permite un parámetro -h, Que permite sufijos numéricos del tipo producido por du -h:

du -hs * | sort -h

Si está utilizando un tipo que no admite -h, Puede instalar GNU Coreutils. Por ejemplo, en un Mac OS X anterior:

brew install coreutils
du -hs * | gsort -h

De sortmanual :

-h, --human-numeric-sort compare human readable numbers (e.g., 2K 1G)

1444
ptman
du | sort -nr | cut -f2- | xargs du -hs
89
cadrian

@ Douglas Leeder, una respuesta más: clasifique la salida legible por humanos de du -h usando otra herramienta. ¡Como Perl!

du -h | Perl -e 'sub h{%h=(K=>10,M=>20,G=>30);($n,$u)=shift=~/([0-9.]+)(\D)/;
return $n*2**$h{$u}}print sort{h($b)<=>h($a)}<>;'

Dividir en dos líneas para adaptarse a la pantalla. Puede usarlo de esta manera o hacerlo de una sola línea, funcionará de cualquier manera.

Salida:

4.5M    .
3.7M    ./colors
372K    ./plugin
128K    ./autoload
100K    ./doc
100K    ./syntax

EDITAR: Después de algunas rondas de golf en PerlMonks , el resultado final es el siguiente:

Perl -e'%h=map{/.\s/;99**(ord$&&7)-$`,$_}`du -h`;[email protected]{sort%h}'
62
Adam Bellaire

Hay una herramienta inmensamente útil que uso llamada ncd que está diseñada para encontrar esas molestas carpetas y archivos de alto uso de disco, y eliminarlos. Está basado en consola, es rápido y ligero, y tiene paquetes en todas las distribuciones principales.

57
neutral
du -k * | sort -nr | cut -f2 | xargs -d '\n' du -sh
44
chrisharris.

Por lo que puedo ver, tienes tres opciones:

  1. Modifique du para ordenar antes de mostrar.
  2. Modifique sort para admitir tamaños humanos para la ordenación numérica.
  3. Postprocese la salida de clasificación para cambiar la salida básica a lectura humana.

También podrías hacer du -k y vive con tamaños en KiB.

Para la opción 3, puede usar el siguiente script:

#!/usr/bin/env python

import sys
import re

sizeRe = re.compile(r"^(\d+)(.*)$")

for line in sys.stdin.readlines():
    mo = sizeRe.match(line)
    if mo:
        size = int(mo.group(1))
        if size < 1024:
            size = str(size)+"K"
        Elif size < 1024 ** 2:
            size = str(size/1024)+"M"
        else:
            size = str(size/(1024 ** 2))+"G"

        print "%s%s"%(size,mo.group(2))
    else:
        print line
21
Douglas Leeder

También tuve ese problema y actualmente estoy usando una solución alternativa:

du -scBM | sort -n

Esto no producirá valores escalados, pero siempre producirá el tamaño en megabytes. Eso es menos que perfecto, pero para mí es mejor que nada (o mostrar el tamaño en bytes).

20
Joachim Sauer

Encontrado esta publicación en otro lugar. Por lo tanto, este script de Shell hará lo que desee sin llamar a du en todo dos veces. Utiliza awk para convertir los bytes sin formato a un formato legible para humanos. Por supuesto, el formato es ligeramente diferente (todo se imprime con una precisión decimal).

#/bin/bash
du -B1 | sort -nr  |awk '{sum=$1;
hum[1024**3]="G";hum[1024**2]="M";hum[1024]="K";
for (x=1024**3; x>=1024; x/=1024){
        if (sum>=x) { printf "%.1f%s\t\t",sum/x,hum[x];print $2;break
}}}'

Ejecutando esto en mi .vim el rendimiento del directorio:

4.4M            .
3.6M            ./colors
372.0K          ./plugin
128.0K          ./autoload
100.0K          ./syntax
100.0K          ./doc

(Espero que 3.6 millones de esquemas de color no sean excesivos).

19
Adam Bellaire

Esta versión usa awk para crear columnas adicionales para ordenar las claves. Solo llama a du una vez. El resultado debería verse exactamente como du.

Lo he dividido en varias líneas, pero puede recombinarse en una sola línea.

du -h |
  awk '{printf "%s %08.2f\t%s\n", 
    index("KMG", substr($1, length($1))),
    substr($1, 0, length($1)-1), $0}' |
  sort -r | cut -f2,3

Explicación:

  • COMIENCE - cree una cadena para indexar para sustituir 1, 2, 3 por K, M, G para agrupar por unidades, si no hay unidad (el tamaño es inferior a 1K), entonces no hay coincidencia y se devuelve un cero (¡perfecto! )
  • imprima los nuevos campos: unidad, valor (para que la ordenación alfa funcione correctamente es de relleno fijo, longitud fija) y la línea original
  • indexar el último carácter del campo de tamaño
  • sacar la porción numérica del tamaño
  • ordenar los resultados, descartar las columnas adicionales

Pruébelo sin el comando cut para ver qué está haciendo.

Aquí hay una versión que ordena dentro del script AWK y no necesita cut:

du -h |
   awk '{idx = sprintf("%s %08.2f %s", 
         index("KMG", substr($1, length($1))),
         substr($1, 0, length($1)-1), $0);
         lines[idx] = $0}
    END {c = asorti(lines, sorted);
         for (i = c; i >= 1; i--)
           print lines[sorted[i]]}'

Aquí hay un ejemplo que muestra los directorios en una forma resumida más compacta. Maneja espacios en el directorio/nombres de archivo.

% du -s * | sort -rn | cut -f2- | xargs -d "\n" du -sh

53G  projects
21G  Desktop
7.2G VirtualBox VMs
3.7G db
3.3G SparkleShare
2.2G Dropbox
272M apps
47M  incoming
14M  bin
5.7M rpmbuild
68K  vimdir.tgz
15
slm

ordenar archivos por tamaño en MB

du --block-size=MiB --max-depth=1 path | sort -n
12
lukmansh

Tengo un simple pero útil python wrapper para du llamado dutop . Tenga en cuenta que nosotros (los mantenedores de coreutils) estamos considerando agregar la funcionalidad para ordenar para ordenar "humano" salida directamente.

9
pixelbeat

Tengo otro:

$ du -B1 | sort -nr | Perl -MNumber::Bytes::Human=format_bytes -F'\t' -lane 'print format_bytes($F[0])."\t".$F[1]'

Me está empezando a gustar Perl. Puede que tengas que hacer un

$ cpan Number::Bytes::Human

primero. Para todos los hackers de Perl: Sí, sé que la parte de clasificación también se puede hacer en Perl. Probablemente la parte du, también.

9
0x89

Este fragmento fue desvergonzado enganchado de 'Jean-Pierre' de http://www.unix.com/Shell-programming-scripting/32555-du-h-sort.html . ¿Hay alguna manera de que pueda darle más crédito?

du -k | sort -nr | awk '
     BEGIN {
        split("KB,MB,GB,TB", Units, ",");
     }
     {
        u = 1;
        while ($1 >= 1024) {
           $1 = $1 / 1024;
           u += 1
        }
        $1 = sprintf("%.1f %s", $1, Units[u]);
        print $0;
     }
    '
8
Bozojoe

Use la bandera "-g"

 -g, --general-numeric-sort
              compare according to general numerical value

Y en mi directorio/usr/local produce resultados como este:

$ du |sort -g

0   ./lib/site_Ruby/1.8/rubygems/digest
20  ./lib/site_Ruby/1.8/rubygems/ext
20  ./share/xml
24  ./lib/Perl
24  ./share/sgml
44  ./lib/site_Ruby/1.8/rubygems/package
44  ./share/mime
52  ./share/icons/hicolor
56  ./share/icons
112 ./share/Perl/5.10.0/YAML
132 ./lib/site_Ruby/1.8/rubygems/commands
132 ./share/man/man3
136 ./share/man
156 ./share/Perl/5.10.0
160 ./share/Perl
488 ./share
560 ./lib/site_Ruby/1.8/rubygems
604 ./lib/site_Ruby/1.8
608 ./lib/site_Ruby
7
Mick T

Encontré este en línea ... parece funcionar bien

du -sh * | tee /tmp/duout.txt | grep G | sort -rn ; cat /tmp/duout.txt | grep M | sort -rn ; cat /tmp/duout.txt | grep K | sort -rn ; rm /tmp/duout.txt
5
Peter Nunn

Aquí está el método simple que uso, uso de recursos muy bajo y le brinda lo que necesita:

du --max-depth=1 | sort -n | awk 'BEGIN {OFMT = "%.0f"} {print $1/1024,"MB", $2}'

0 MB ./etc
1 MB ./mail
2 MB ./tmp
123 MB ./public_html
4
JacobN

Aprendí awk al inventar este ejemplo ayer. Me tomó algo de tiempo, pero fue muy divertido, y aprendí a usar awk.

Se ejecuta solo du una vez, y tiene una salida muy similar a du -h

du --max-depth=0 -k * | sort -nr | awk '{ if($1>=1024*1024) {size=$1/1024/1024; unit="G"} else if($1>=1024) {size=$1/1024; unit="M"} else {size=$1; unit="K"}; if(size<10) format="%.1f%s"; else format="%.0f%s"; res=sprintf(format,size,unit); printf "%-8s %s\n",res,$2 }'

Muestra números por debajo de 10 con un punto decimal.

4
marlar

Otro:

du -h | Perl -e'
@l{ K, M, G } = ( 1 .. 3 );
print sort {
    ($aa) = $a =~ /(\w)\s+/;
    ($bb) = $b =~ /(\w)\s+/;
    $l{$aa} <=> $l{$bb} || $a <=> $b
  } <>'
4
Dimitre Radoulov

du -cka --max-depth = 1/var/log | sort -rn | cabeza -10 | awk '{print ($ 1)/1024, "MB", $ 2'}

3
Patrick

Si necesita manejar espacios, puede usar lo siguiente

 du -d 1| sort -nr | cut -f2 | sed 's/ /\\ /g' | xargs du -sh

La declaración adicional de sed ayudará a aliviar los problemas con las carpetas con nombres como Application Support

2
Chealion

Voilà:

du -sk /var/log/* | sort -rn | awk '{print $2}' | xargs -ia du -hs "a"
1
weeheavy

Aquí hay muchas respuestas, muchas de las cuales son duplicadas. Veo tres tendencias: pasar por una segunda llamada du, usar código Shell/awk complicado y usar otros idiomas.

Aquí hay una solución compatible con POSIX usando d y awk que debería funcionar en todos los sistemas.

He adoptado un enfoque ligeramente diferente, agregando -x para asegurarnos de que permanecemos en el mismo sistema de archivos (solo necesito esta operación cuando tengo poco espacio en disco, entonces, ¿por qué eliminar cosas que he montado dentro de este árbol FS o movido y enlace simbólico?) y muestra unidades constantes para facilitar el análisis visual. En este caso, normalmente elijo ¡no para ordenar para poder ver mejor la estructura jerárquica.

Sudo du -x | awk '
  $1 > 2^20 { s=$1; $1=""; printf "%7sG%s\n", sprintf("%.2f",s/2^21), $0 }'

(Dado que esto está en unidades consistentes, puede agregar | sort -n si realmente quieres ordenar resultados ed.)

Esto filtra cualquier directorio cuyo contenido (acumulativo) no supere los 512 MB y luego muestre los tamaños en gigabytes. Por defecto, du usa un tamaño de bloque de 512 bytes (por lo que la condición de awk es de 220 bloques es de 512 MB y sus 221 divisor convierte las unidades a GB - podríamos usar du -kx con $1 > 512*1024 y s/1024^2 para ser más legible para los humanos). Dentro de la condición awk, establecemos s en el tamaño para que podamos eliminarlo de la línea ($0). Esto retiene el delimitador (que se contrae en un solo espacio), por lo que el final %s representa un espacio y luego el nombre del directorio agregado. %7s alinea el redondeado %.2f Tamaño de GB (aumentar a %8s si tiene> 10 TB).

A diferencia de la mayoría de las soluciones aquí, esto admite correctamente directorios con espacios en sus nombres (aunque cada solución, incluida esta uno, manejará mal los nombres de directorio que contienen saltos de línea).

1
Adam Katz

Otra solución awk -

du -k ./* | sort -nr | 
awk '
{split("KB,MB,GB",size,",");}
{x = 1;while ($1 >= 1024) 
{$1 = $1 / 1024;x = x + 1} $1 = sprintf("%-4.2f%s", $1, size[x]); print $0;}'


[jaypal~/Desktop/Reference]$ du -k ./* | sort -nr | awk '{split("KB,MB,GB",size,",");}{x = 1;while ($1 >= 1024) {$1 = $1 / 1024;x = x + 1} $1 = sprintf("%-4.2f%s", $1, size[x]); print $0;}'
15.92MB ./Personal
13.82MB ./Personal/Docs
2.35MB ./Work Docs
1.59MB ./Work Docs/Work
1.46MB ./Personal/Raa
584.00KB ./scan 1.pdf
544.00KB ./Personal/Resume
44.00KB ./Membership.xlsx
16.00KB ./Membership Transmittal Template.xlsx
1
user96753

http://dev.yorhel.nl/ncd

comando: ncdu

Navegación de directorios, clasificación (nombre y tamaño), gráficos, legibles por humanos, etc.

1
Adam Eickhoff

Había estado usando la solución proporcionada por @ptman, pero un cambio reciente en el servidor hizo que ya no fuera viable. En cambio, estoy usando el siguiente script bash:

#!/bin/bash
# File: duf.sh
# list contents of the current directory by increasing 
#+size in human readable format

# for some, "-d 1" will be "--maxdepth=1"
du -k -d 1 | sort -g | awk '
{
if($1<1024)
    printf("%.0f KB\t%s",$1,$2);
else if($1<1024*1024)
    printf("%.1f MB\t%s",$1/1024,$2);
else
    printf("%.1f GB\t%s",$1/1024/1024,$2);
}'
1
Keith Yoder

du -s * | sort -nr | corte -f2 | xargs du -sh

1
ageek2remember

Aquí hay un ejemplo

du -h /folder/subfolder --max-depth=1 | sort -hr

Devoluciones:

233M    /folder/subfolder
190M    /folder/subfolder/myfolder1
15M     /folder/subfolder/myfolder4
6.4M    /folder/subfolder/myfolder5
4.2M    /folder/subfolder/myfolder3
3.8M    /folder/subfolder/myfolder2

También puedes agregar | head -10 para encontrar las 10 principales o cualquier cantidad de subcarpetas en el directorio especificado.

1
ode2k

Este es el alias que tengo en mi perfil.

alias du = 'Sudo du -xh --max-depth = 1 | ordenar -h '

sort -h es lo que realmente ayuda aquí a la pregunta formulada.

Otras opciones útiles son du -x para permanecer en el mismo sistema de archivos; también Sudo ayuda a no ver errores si hay directorios que no se pueden leer en todo el mundo. Además, siempre hago du --max-depth = 1, luego profundizo más, etc.

0
Tagar

¡Sin embargo, otro du script!

Como ya hay mucha respuesta, acabo de publicar mi propio script allí. Lo uso desde hace más de ocho años.

Esto podría correr por

/somepath/rdu.sh [-b] [/somepath] [minSize]

dónde

  • bandera opcional -b diga que use ¡recuento de bytes en lugar de bloque contar
  • opcional ¡ruta como primer argumento, directorio actual si es predeterminado.
  • si no se proporciona un segundo argumento, el tamaño mínimo a imprimir es 256Mb.

La salida podría verse así:

\___   3.01G                 21.67%                .cache
|   \___   1.37G                 45.54%                mozilla
|   |   \___   1.37G                100.00%                firefox
|   |   |   \___ 581.71M                 41.48%                billiethek.default
|   |   |   |   \___ 522.64M                 89.85%                cache2
|   |   |   |   |   \___ 522.45M                 99.96%                entries
...

Ahí está el guión:

#!/bin/bash

if [ "$1" == "-b" ] ;then
    shift
    units=(b K M G T P)
    duargs="-xbs"
    minsize=${2:-$((256*1024**2))}
else
    units=(K M G T P)
    duargs="-xks"
    minsize=${2:-$((256*1024))}
fi

humansize() {
    local _c=$1 _i=0
    while [ ${#_c} -gt 3 ] ;do
        ((_i++))
        _c=$((_c>>10))
    done
    _c=$(( ( $1*1000 ) >> ( 10*_i ) ))
    printf ${2+-v} $2 "%.2f%s" ${_c:0:${#_c}-3}.${_c:${#_c}-3} ${units[_i]}
}
percent() {
    local p=000$((${1}00000/$2))
    printf ${3+-v} $3 "%.2f%%" ${p:0:${#p}-3}.${p:${#p}-3}
}

device=$(stat -c %d "${1:-.}")
printf -v sep "%16s" ""

rdu() {
    local _dir="$1" _spc="$2" _crt _siz _str _tot _pct
    while read _siz _crt;do
        if [ "$_crt" = "total"  ]; then
            _tot=$_siz
        else
            [ "$_tot" ] || _tot=$_siz
            if [ $_siz -gt $minsize ];then
                humansize $_siz _str
                percent $_siz $_tot _pct
                printf "%s\___ %7s%s%7s%s%s\n" \
                    "$_spc" $_str "$sep" $_pct "$sep" "${_crt##*/}"
                [ -d "$_crt" ] &&
                [ $(stat -c %d "$_crt") -eq $device ] &&
                rdu "$_crt" "|   $_spc"
            fi
        fi
    done < <(
        find "$_dir" -mindepth 1 -maxdepth 1 -xdev \
            \( -type f -o -type d \) -printf "%D;%p\n" |
            sed -ne "s/^${device};//p" |
            tr \\n \\0 |
            xargs -0 du ${duargs}c |
            sort -nr
    )
}

rdu "${1:-.}"

Y no, no los publicaré en Git***.xxx.

Puede mostrarlos allí o descargar la secuencia de comandos allí.

0
F. Hauri

Aquí está mi solución, un script bash simple que solo llama du una vez, y muestra solo directorios de tamaño 1 MB o más:

#!/bin/env bash
# Usage: my_du.sh [subdirectory levels]
#   For efficiency, only calls "du" once, and stores results in a temp file
#   Stephen Becker, 2/23/2010

if [ $# -gt 0 ]; then
# You may prefer, as I do, to just summarize the contents of a directory
# and not view the size of its subdirectories, so use this:
    du -h --max-depth $1 > temp_du_file
else
    du -h > temp_du_file
fi


# Show all directories of size > 1 GB:
cat temp_du_file | grep "^\([0-9]\|\.\)\+G" | sort -nr
# Show all directories of size > 1 MB:
cat temp_du_file | grep "^\([0-9]\|\.\)\+M" | sort -nr

rm temp_du_file
0
Stephen

Al menos con las herramientas habituales, esto será difícil debido al formato en que se encuentran los números legibles por humanos (tenga en cuenta que la clasificación hace un "buen trabajo" aquí, ya que clasifica los números: 508, 64, 61, 2, 2) simplemente no puede ordenar los números de coma flotante con un multiplicador adicional).

Lo intentaría al revés: use la salida de "du | sort -n -r" y luego convierta los números a un formato legible para humanos con algún script o programa.

0
schnaader

Lo que puedes probar es:

for i in `du -s * | sort -n | cut -f2`
do
  du -h $i;
done

Espero que ayude.

0
Christian Witts
du | sort -nr | awk '{ cmd = "du -h -d0 "$2"| cut -f1"; cmd | getline human; close(cmd); print human"\t"$2 }'
0
Nathan de Vries

La siguiente solución es similar a la original de cadrian, sin embargo, esto solo ejecutará 2 du comandos en lugar de un du para cada directorio en el árbol.

du -hs `du |sort -g |cut -f2- `

Sin embargo, la solución de Cardrian es más sólida ya que lo anterior no funcionará para árboles muy poblados, ya que podría exceder el límite del tamaño de los argumentos pasados ​​a du

0
Steve Weet

Basada en la lógica de esta línea , escribí un script que proporciona una salida du (1) ordenada por humanos. Aparte de requerir el -h indicador de legibilidad humana, no requiere otros comandos no compatibles con POSIX.

Está disponible en https://github.com/pleappleappleap/sorted-human-d .

0
Tripp Kinetics

¿Por qué no arrojar otro sombrero al ring? ... es una pregunta antigua, pero aquí hay un ejemplo que es (en su mayoría) script de Shell puro (fwiw), es decir, solo bash y no Perl/python/awk/etc. Entonces, en ese sentido, tal vez ofrece algo nuevo a la discusión (o no). Calcula el tamaño del archivo solo una vez, pero imprime en varias unidades (mi preferencia). (La versión no simplificada incluye getopts que excluye "GB" si no se desea).

#!/bin/bash

printf -- ' %9s %9s %9s       %-30s\n' 'K'        'M'        'G'        'Path'
printf -- ' %9s %9s %9s       %-30s\n' '--------' '--------' '--------' '-----------'
du -sk "[email protected]" | while read val; do
    file=$(echo "$val" | cut -f2-)
    size_k=$(echo "$val"  | cut -f1)
    printf ' %9s %9s %9s       %-30s\n' \
          ${size_k}  \
          $(( size_k / 1024 ))  \
          $(( size_k / 1024 / 1024 ))  \
          "$file"
  done | sort -n
0
michael

Se ordena en orden descendente.

du -s ./* | sort -n| cut -f 2-| xargs du -sh {}
0
Peter Nduati