Como posso ordenar du -h output por tamanho

844

Eu preciso de uma lista de resultados legíveis para humanos.

No entanto, du não tem uma opção "classificar por tamanho", e canalizar para sort não funciona com o sinalizador legível.

Por exemplo, executando:

du | sort -n -r 

Exibe um uso de disco classificado por tamanho (decrescente):

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

No entanto, executá-lo com o sinalizador legível por humanos não é classificado corretamente:

du -h | sort -n -r

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

Alguém sabe de uma maneira de classificar du -h por tamanho?

    
por Tom Feiner 25.02.2009 / 14:42

38 respostas

1171

A partir de GNU Coreutils 7.5 lançado em agosto de 2009, sort permite um parâmetro -h , que permite sufixos numéricos do tipo produzido por du -h :

du -hs * | sort -h

Se você está usando uma classificação que não suporta -h , você pode instalar o GNU Coreutils. Por exemplo. em um Mac OS X antigo:

brew install coreutils
du -hs * | gsort -h

De sort manual:

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

    
por 01.07.2010 / 14:29
83
du | sort -nr | cut -f2- | xargs du -hs
    
por 25.02.2009 / 14:52
59

@ Douglas Leeder, mais uma resposta: Ordene a saída legível por humanos a partir de duh usando outra ferramenta. 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 em duas linhas para ajustar a exibição. Você pode usá-lo desta forma ou torná-lo um one-liner, ele funcionará de qualquer forma.

Saída:

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

EDIT: Depois de algumas partidas de golfe no PerlMonks , o resultado final é o seguinte:

perl -e'%h=map{/.\s/;99**(ord$&&7)-$',$_}'du -h';die@h{sort%h}'
    
por 25.02.2009 / 22:04
50

Existe uma ferramenta imensamente útil que eu uso chamada ncdu que é projetada para encontrar essas pastas e arquivos irritantes com alto uso de disco e removê-los. É baseado em console, rápido e leve, e tem pacotes em todas as principais distribuições.

    
por 25.02.2009 / 21:39
43
du -k * | sort -nr | cut -f2 | xargs -d '\n' du -sh
    
por 25.02.2009 / 15:01
20

Até onde eu vejo, você tem três opções:

  1. Altere du para classificar antes da exibição.
  2. Altere sort para suportar tamanhos humanos para classificação numérica.
  3. Postar o resultado da classificação para alterar a saída básica para legível por humanos.

Você também pode fazer du -k e viver com tamanhos em KiB.

Para a opção 3, você pode usar o seguinte 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
    
por 25.02.2009 / 14:53
19

Eu tive esse problema também e atualmente estou usando uma solução alternativa:

du -scBM | sort -n

Isso não produzirá valores escalados, mas sempre produzirá o tamanho em megabytes. Isso é menos que perfeito, mas para mim é melhor que nada (ou exibir o tamanho em bytes).

    
por 25.02.2009 / 14:56
18

Encontrado esta postagem em outro lugar. Portanto, este script de shell fará o que você quiser sem chamar du em tudo duas vezes. Ele usa awk para converter os bytes brutos em um formato legível por humanos. Naturalmente, a formatação é um pouco diferente (tudo é impresso com precisão de uma casa 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
}}}'

A execução deste no meu .vim diretório gera:

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

(Espero que 3,6 milhões de esquemas de cores não sejam excessivos.)

    
por 25.02.2009 / 15:09
14

Esta versão usa awk para criar colunas extras para as chaves de classificação. Apenas chama du uma vez. A saída deve ser exatamente como du .

Eu o divido em várias linhas, mas ele pode ser recombinado em uma linha única.

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

Explicação:

  • BEGIN - cria uma string para indexar para substituir 1, 2, 3 para K, M, G para agrupar por unidades, se não houver unidade (o tamanho é menor que 1K), não há correspondência e um zero é retornado (perfeito!)
  • imprime os novos campos - unidade, valor (para fazer com que a classificação alfa funcione corretamente é preenchida com zero, de comprimento fixo) e linha original
  • indexa o último caractere do campo de tamanho
  • retire a parte numérica do tamanho
  • classifique os resultados, descarte as colunas extras

Experimente sem o comando cut para ver o que está fazendo.

Aqui está uma versão que faz a classificação no script AWK e não precisa de 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]]}'
    
por 04.09.2009 / 19:06
13

Aqui está um exemplo que mostra os diretórios em um formulário resumido mais compacto. Ele lida com espaços no diretório / nomes de arquivos.

% 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
    
por 11.08.2011 / 05:08
9

classifica arquivos por tamanho em MB

du --block-size=MiB --max-depth=1 path | sort -n
    
por 11.03.2013 / 12:17
8

Eu tenho um invólucro de python simples, mas útil, chamado du dutop . Note que nós (os mantenedores do coreutils) estamos considerando adicionar a funcionalidade para classificar a saída "humana" diretamente.

    
por 18.03.2009 / 23:10
8

Tenho outro:

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

Estou começando a gostar de perl. Você pode ter que fazer um

$ cpan Number::Bytes::Human

primeiro. Para todos os hackers perl lá fora: Sim, eu sei que a parte do tipo também pode ser feita em perl. Provavelmente a du parte também.

    
por 04.09.2009 / 10:10
6

Use o sinalizador "-g"

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

E no meu diretório / usr / local produz uma saída assim:

$ 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
    
por 25.02.2009 / 18:15
6

Esse trecho foi sem vergonha roubado de "Jean-Pierre" do link . Existe uma maneira que eu possa dar crédito a ele?

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;
     }
    '
    
por 15.09.2009 / 17:50
4

Outro:

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
  } <>'
    
por 18.03.2009 / 23:58
3

Encontrei este aqui ... parece funcionar OK

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
    
por 31.08.2017 / 15:49
2

Eu aprendi awk de inventar este exemplo ontem. Demorou algum tempo, mas foi muito divertido, e aprendi a usar o awk.

Ele é executado apenas uma vez e tem uma saída muito semelhante 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 }'

Mostra números abaixo de 10 com um ponto decimal.

    
por 01.07.2010 / 10:33
2

Aqui está o método simples que uso, o uso de recursos muito baixo e você obtém o que precisa:

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
    
por 01.07.2011 / 07:48
2

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

    
por 24.08.2011 / 16:50
1

Se você precisar gerenciar espaços, use o seguinte

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

A instrução sed adicional ajudará a aliviar problemas com pastas com nomes como Suporte a aplicativos

    
por 18.03.2009 / 22:54
1

Voilà:

du -sk /var/log/* | sort -rn | awk '{print $2}' | xargs -ia du -hs "a"
    
por 01.07.2010 / 15:44
1

link

comando

: ncdu

Navegação no diretório, classificação (nome e tamanho), gráficos, legível, etc ...

    
por 29.11.2011 / 21:07
1

Outra awk solution -

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
    
por 22.12.2011 / 07:10
1

Eu estava usando a solução fornecida pelo @ptman, mas uma alteração recente no servidor não tornou mais viável. Em vez disso, estou usando o seguinte script:

#!/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);
}'
    
por 18.04.2012 / 20:35
1

Há muitas respostas aqui, muitas das quais são duplicatas. Eu vejo três tendências: percorrer um segundo du call, usar código shell / awk complicado e usar outros idiomas.

Aqui está uma solução compatível com POSIX usando du e awk que deve funcionar em todos os sistemas.

Adotei uma abordagem um pouco diferente, adicionando -x para garantir que permaneçamos no mesmo sistema de arquivos (eu só preciso dessa operação quando estou com pouco espaço em disco, então por que eliminar coisas que montei esta árvore de FS ou movido e symlinked de volta?) e exibindo unidades constantes para facilitar a análise visual. Nesse caso, eu geralmente escolho não para classificar, para que eu possa ver melhor a estrutura hierárquica.

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

(Como isso está em unidades consistentes, você pode acrescentar | sort -n se realmente quiser classificar ed resultados.)

Isso filtra qualquer diretório cujo conteúdo (cumulativo) não exceda 512 MB e, em seguida, exibe tamanhos em gigabytes. Por padrão, du usa um tamanho de bloco de 512 bytes (então a condição de 2 20 do awk é de 512MB e seu 2 21 divisor converte as unidades para GB - poderíamos usar du -kx com $1 > 512*1024 e s/1024^2 para ser mais legível por humanos). Dentro da condição do awk, definimos s para o tamanho para que possamos removê-lo da linha ( $0 ). Isso retém o delimitador (que é reduzido a um único espaço), portanto, o% final %s representa um espaço e, em seguida, o nome do diretório agregado. %7s alinha o tamanho arredondado do %.2f GB (aumente para %8s se você tiver > 10 TB).

Diferentemente da maioria das soluções aqui, isso suporta diretórios com espaços em seus nomes (embora todas soluções, incluindo esta, manipularão incorretamente nomes de diretório contendo quebras de linha) .

    
por 25.02.2017 / 01:31
0

Pelo menos com as ferramentas usuais, isso será difícil por causa do formato em que estão os números legíveis por humanos (note que o tipo faz um "bom trabalho" aqui quando classifica os números - 508, 64, 61, 2, 2 - simplesmente não é possível classificar números de ponto flutuante com um multiplicador adicional).

Eu tentaria ao contrário - use a saída de "du | sort -n -r" e depois converta os números para o formato legível por humanos com algum script ou programa.

    
por 25.02.2009 / 14:52
0

O que você pode tentar é:

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

Espero que ajude.

    
por 25.02.2009 / 15:03
0
du | sort -nr | awk '{ cmd = "du -h -d0 "$2"| cut -f1"; cmd | getline human; close(cmd); print human"\t"$2 }'
    
por 25.02.2009 / 15:14
0

A solução a seguir é semelhante ao original do cadriano, no entanto, isso só executará 2 du comandos, ao contrário de um du para cada diretório na árvore.

du -hs 'du |sort -g |cut -f2- '
No entanto, a solução de Cardrian é mais robusta, pois o acima não funcionará para árvores muito densamente povoadas, pois pode exceder o limite do tamanho dos argumentos passados para du

    
por 27.02.2009 / 13:14