Como você classifica du saída por tamanho?

180

Como você classifica du -sh /dir/* por tamanho? Eu li um site que dizia usar | sort -n , mas isso obviamente não está certo. Aqui está um exemplo que está errado.

[~]# du -sh /var/* | sort -n
0       /var/mail
1.2M    /var/www
1.8M    /var/tmp
1.9G    /var/named
2.9M    /var/run
4.1G    /var/log
8.0K    /var/account
8.0K    /var/crash
8.0K    /var/cvs
8.0K    /var/games
8.0K    /var/local
8.0K    /var/nis
8.0K    /var/opt
8.0K    /var/preserve
8.0K    /var/racoon
12K     /var/aquota.user
12K     /var/portsentry
16K     /var/ftp
16K     /var/quota.user
20K     /var/yp
24K     /var/db
28K     /var/empty
32K     /var/lock
84K     /var/profiles
224M    /var/netenberg
235M    /var/cpanel
245M    /var/cache
620M    /var/lib
748K    /var/spool
    
por xenoterracide 09.12.2010 / 12:17

17 respostas

224

Se você tem o GNU coreutils (comum na maioria das distribuições Linux), você pode usar du -sh * | sort -h . A opção -h informa sort que a entrada é o formato legível por humanos (número com unidade).

Esse recurso foi adicionado ao GNU Core Utilities 7.5 em agosto de 2009 .

Note:

If you are using Mac OSX, you need install coreutils with brew install coreutils, then use gsort as drop-in replacement of sort

    
por 09.12.2010 / 12:58
46

Tente usar o sinalizador -k para contar blocos de 1K em vez de usar legíveis. Então, você tem uma unidade comum e pode facilmente fazer uma classificação numérica.

du -ck | sort -n

Você não precisa, explicitamente, de unidades humanas, mas, se o fez, há várias maneiras de fazê-lo. Muitos parecem usar a técnica de bloqueio de 1K acima, e então fazer uma segunda chamada para du.

link

Se você quiser ver as unidades KB adicionadas, use:

du -k | sed -e 's_^\([0-9]*\)_ KB_' | sort -n
    
por 09.12.2010 / 14:04
16

Se você não tiver uma versão recente do GNU coreutils , você pode chamar du sem -h para obter saída classificável e produzir uma saída amigável com um pouco de pós-processamento. Isso tem a vantagem de funcionar mesmo se sua versão de du não tiver o sinalizador -h .

du -k | sort -n | awk '
    function human(x) {
        if (x<1000) {return x} else {x/=1024}
        s="kMGTEPZY";
        while (x>=1000 && length(s)>1)
            {x/=1024; s=substr(s,2)}
        return int(x+0.5) substr(s,1,1)
    }
    {gsub(/^[0-9]+/, human($1)); print}'

Se você quiser sufixos SI (ou seja, múltiplos de 1000 em vez de 1024), altere 1024 para 1000 no corpo do ciclo while . (Observe que a condição 1000 está prevista, para que você obtenha, por exemplo, 1M em vez de 1000k .)

Se o seu du tiver uma opção para exibir tamanhos em bytes (por exemplo, -b ou -B 1 - observe que isso pode ter o efeito colateral de contar os tamanhos reais do arquivo em vez do uso do disco), adicione um espaço ao início de s (ou seja, s=" kMGTEPYZ"; ) ou adicione if (x<1000) {return x} else {x/=1024} no início da função human .

A exibição de um dígito decimal para números no intervalo de 1 a 10 é deixada como um exercício para o leitor.

    
por 09.12.2010 / 20:06
7

Se você não tem sort -h , pode fazer isso:

du -sh * | sed 's/\([[:digit:]]\)\t/B\t/' | sed 's/\(.\t\)/\t/' | sed 's/G\t/Z\t/' | sort -n -k 2d,2 -k 1n,1 | sed 's/Z\t/G\t/'

Isso obtém a lista du, separa o sufixo e classifica usando isso. Como não há sufixo para < 1K, o primeiro sed adiciona um B (para byte). O segundo sed adiciona um delimitador entre o dígito e o sufixo. O terceiro sed converte G para Z de modo que seja maior que M; Se você tiver arquivos terabytes, terá que converter G para Y e T para Z. Por fim, classificamos pelas duas colunas e substituímos o sufixo G.

    
por 09.12.2010 / 14:45
6

No OS X, você pode instalar os coreutils necessários por meio do Homebrew :

brew install coreutils

Com isso, você terá gsort , que inclui o parâmetro de linha de comando -h .

    
por 29.08.2014 / 11:54
4

Este pequeno script Perl faz o truque. Salve como duh (ou o que você quiser) e chame com duh /dir/*

#!/usr/bin/perl -w
use strict;

my @line;

sub to_human_readable {
        my ($number) = @_;
        my @postfix = qw( k M G T P );
        my $post;
        my $divide = 1;
        foreach (@postfix) {
                $post = $_;
                last if (($number / ($divide * 1024)) < 1);
                $divide = $divide * 1024;
        }
        $number = int($number/$divide + 0.5);
        return $number . $post;
}

sub trimlengthright {
        my ($txt, $len) = @_;
        if ( length($txt) >= $len ) {
                $txt = substr($txt,0,$len - 1) . " ";
        } else {
                $txt = $txt . " " x ($len - length($txt));
        }
        return $txt;
}

sub trimlengthleft {
        my ($txt, $len) = @_;
        if ( length($txt) >= $len ) {
                $txt = substr($txt,0,$len - 1) . " ";
        } else {
                $txt = " " x ($len - length($txt)) . $txt;
        }
        return $txt;
}

open(DF,"du -ks @ARGV | sort -n |");
while (<DF>) {
        @line = split;
        print &trimlengthleft(&to_human_readable($line[0]),5)," "; # size
        print &trimlengthright($line[1],70),"\n"; # directory
}
close DF;
    
por 09.12.2010 / 13:35
4

Como o Mac OS X não possui a opção -h para sort , tentei e aprendi sed e awk em uma primeira tentativa:

du -sk * | sort -g | awk '{ numBytes = $1 * 1024; numUnits = split("B K M G T P", unit); num = numBytes; iUnit = 0; while(num >= 1024 && iUnit + 1 < numUnits) { num = num / 1024; iUnit++; } $1 = sprintf( ((num == 0) ? "%6d%s " : "%6.1f%s "), num, unit[iUnit + 1]); print $0; }'

é uma linha longa. Expandido, é:

du -sk * | sort -g | awk '{ 

    numBytes = $1 * 1024; 
    numUnits = split("B K M G T P", unit); 
    num = numBytes; 
    iUnit = 0; 

    while(num >= 1024 && iUnit + 1 < numUnits) { 
        num = num / 1024; 
        iUnit++; 
    } 

    $1 = sprintf( ((num == 0) ? "%6d%s " : "%6.1f%s "), num, unit[iUnit + 1]);
    print $0; 

}'

Eu testei no Mac OS X Mavericks, Yosemite, Ubuntu 2014-04, com awk sendo o padrão awk (que é nawk , porque awk e nawk apontam para /usr/bin/mawk ) ou gawk, e todos eles trabalharam.

Aqui está uma amostra da saída em um Mac:

     0B  bar
     0B  foo
   4.0K  wah
  43.0M  Documents
   1.2G  Music
   2.5G  Desktop
   4.7G  Movies
   5.6G  VirtualBox VMs
   9.0G  Dropbox
  11.7G  Library
  21.2G  Pictures
  27.0G  Downloads

em vez de du -sk * , vi na resposta de @ Stefan, onde o total geral também é exibido e sem atravessar nenhum ponto de montagem do sistema de arquivos, usando du -skcx *

    
por 22.04.2015 / 10:13
1

Aqui está o que eu uso no Ubuntu 10.04, CentOS 5.5, FreeBSD e Mac OS X.

Eu peguei emprestada a idéia de www.geekology .co.za / e earthinfo.org , assim como os infames patos do "Linux Server Hacks" da O'Reilly. Ainda estou adaptando às minhas necessidades. Este ainda é um trabalho em andamento (Como em, eu estava trabalhando nisso no trem esta manhã.):

#! /usr/bin/env bash
ducks () {
    du -cks -x | sort -n | while read size fname; do
        for unit in k M G T P E Z Y; do
            if [ $size -lt 1024 ]; then
                echo -e "${size}${unit}\t${fname}"
                break
            fi
            size=$((size/1024))
        done
    done
}
ducks > .ducks && tail .ducks

Aqui está a saída:

stefan@darwin:~ $ ducks
32M src
42M .cpan
43M .macports
754M    doc
865M    Work
1G  .Trash
4G  Library
17G Downloads
30G Documents
56G total

stefan@darwin:~ $
    
por 09.12.2010 / 23:33
1

Enlouqueça com este script -

$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;}'
    
por 18.12.2011 / 08:39
1

Na ausência do GNU sort -h , isso deve funcionar na maioria dos ambientes UNIX:

join -1 2 -2 2 <(du -sk /dir/* 2>/dev/null | sort -k2,2) <(du -sh /dir/* 2>/dev/null | sort -k2,2) | sort -nk2,2 | awk '{ print $3 "\t" $1 }'
    
por 06.11.2018 / 15:04
0

Esse manipula nomes de arquivos com espaços em branco ou apóstrofos e funciona em sistemas que não suportam xargs -d ou sort -h :

du -s * | sort -n | cut -f2 | tr '\n' '
368K    diskmanagementd
392K    racoon
468K    coreaudiod
472K    securityd
660K    sshd
3.6M    php-fpm
' | xargs -0 -I {} du -sh "{}"

que resulta em:

du -s * | sort -n | cut -f2 | tr '\n' '
368K    diskmanagementd
392K    racoon
468K    coreaudiod
472K    securityd
660K    sshd
3.6M    php-fpm
' | xargs -0 -I {} du -sh "{}"
    
por 23.11.2014 / 20:48
0

Isso classificará a saída em ordem decrescente de tamanho:

du -sh /var/* | sort -k 1rn

Isso classificará a saída em ordem crescente de tamanho:

du -sh /var/* | sort -k 1n

PS: isso pode ser usado para classificar por qualquer coluna, mas os valores das colunas devem estar no mesmo formato

    
por 17.01.2017 / 15:28
0

Testado no Solaris!

du -kh | sort -nk1 | grep [0-9]K && du -kh | sort -nk1 | grep [0-9]M && du -kh | sort -nk1 | grep [0-9]G

Isso produzirá todos os tamanhos de diretório de forma recursiva, na parte inferior será o maior diretório em Gigabytes e o menor em Kilobytes.

    
por 03.02.2017 / 10:37
0

O maior está no fundo:

du -sh * | sort -h
    
por 18.05.2018 / 22:47
-1

Para ordenar por tamanho em MB

du --block-size=MiB --max-depth=1 path | sort -n
    
por 11.03.2013 / 11:46
-2

Este script é ainda mais fácil:

for i in G M K; do du -h -d1 / | grep [0-9]$i | sort -n; done
    
por 17.10.2013 / 12:22
-2

para OSX

du -h -k  {PATH} | sort -n
    
por 10.10.2015 / 09:23