ti-enxame.com

Como posso ordenar du -h de saída por tamanho

Preciso obter uma lista de saída duplamente legível por humanos.

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

Por exemplo, executando:

du | sort -n -r 

Produz um uso classificado do disco 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 classifica corretamente:

du -h | sort -n -r

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

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

1029
Tom Feiner

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ê estiver usando uma classificação que não suporta -h, Poderá instalar GNU Coreutils. Por exemplo, em um Mac OS X mais antigo:

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, mais uma resposta: classifique a saída legível por humanos de du -h 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)}<>;'

Divida em duas linhas para caber na tela. Você pode usá-lo dessa maneira ou torná-lo único, pois funcionará de qualquer maneira.

Resultado:

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

EDIT: Após algumas rodadas de golfe em PerlMonks , o resultado final é o seguinte:

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

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

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

Tanto quanto posso ver, 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. Pós-processamento da saída de classificação para alterar a saída básica para legível por humanos.

Você também pode fazer du -k e viva com tamanhos no 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
21
Douglas Leeder

Eu também tive esse problema 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).

20
Joachim Sauer

Encontrado esta postagem em outro lugar. Portanto, esse script do Shell fará o que você deseja sem chamar du em tudo duas vezes. Ele usa awk para converter os bytes brutos em um formato legível por humanos. Obviamente, 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
}}}'

Executando isso no meu .vim diretório produz:

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.)

19
Adam Bellaire

Esta versão usa awk para criar colunas extras para chaves de classificação. Só chama du uma vez. A saída deve ser exatamente igual a du.

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

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 - crie uma string para indexar para substituir 1, 2, 3 por K, M, G por agrupamento por unidades, se não houver nenhuma unidade (o tamanho for menor que 1K), não haverá correspondência e um zero será retornado (perfeito! )
  • imprima os novos campos - unidade, valor (para fazer a classificação alfa funcionar corretamente, é preenchido com zero, comprimento fixo) e linha original
  • indexar o último caractere do campo 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]]}'
15

Aqui está um exemplo que mostra os diretórios em um formato 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
15
slm

classificar arquivos por tamanho em MB

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

Eu tenho um simples mas útil python wrapper para du chamado dutop . Observe que nós (os mantenedores do coreutils) estamos pensando em adicionar a funcionalidade para classificar para classificar "human" saída diretamente.

9
pixelbeat

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 do Perl. Você pode ter que fazer uma

$ cpan Number::Bytes::Human

primeiro. Para todos os hackers do Perl por aí: Sim, eu sei que a parte de classificação também pode ser feita no Perl. Provavelmente a parte dupla também.

9
0x89

Esse trecho foi descaradamente descarado de 'Jean-Pierre' de http://www.unix.com/Shell-programming-scripting/32555-du-h-sort.html . Existe uma maneira de melhor creditar 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;
     }
    '
8
Bozojoe

Use o sinalizador "-g"

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

E no meu diretório/usr/local produz 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

Encontrei este on-line ... 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
5
Peter Nunn

Aqui está o método simples que eu uso, uso muito baixo de recursos e fornece o que você 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
4
JacobN

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

Ele roda apenas du uma vez e tem uma saída muito semelhante à 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.

4
marlar

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
  } <>'
4
Dimitre Radoulov

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

3
Patrick

Se você precisar manipular espaços, poderá usar 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

2
Chealion

Voilà:

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

Há muitas respostas aqui, muitas das quais são duplicadas. Vejo três tendências: passando por uma segunda ligação, usando código Shell/awk complicado e usando outros idiomas.

Aqui está uma solução compatível com POSIX usando d 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 tenho pouco espaço em disco, por que eliminar todas as coisas que montei nessa FS ou movi a árvore e exibindo ligações simbólicas?) e exibindo unidades constantes para facilitar a análise visual.Neste caso, normalmente 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 anexar | sort -n se você realmente deseja classificar resultados editados.)

Isso filtra qualquer diretório cujo conteúdo (cumulativo) não exceda 512 MB e exibe tamanhos em gigabytes. Por padrão, du usa um tamanho de bloco de 512 bytes (a condição do awk de 220 blocos é de 512MB e seus 221 divisor converte as unidades em 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 awk, definimos s para o tamanho para removê-lo da linha ($0). Isso mantém o delimitador (que é recolhido em um único espaço); portanto, o final %s representa um espaço e, em seguida, o nome do diretório agregado. %7s alinha o arredondado %.2f Tamanho do GB (aumente para %8s se você tiver> 10 TB).

Diferentemente da maioria das soluções aqui, , ele suporta diretórios com espaços em seus nomes (embora every solução, incluindo esta um, manipulará incorretamente os nomes de diretório que contêm quebras de linha).

1
Adam Katz

Outra solução 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

command: ncdu

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

1
Adam Eickhoff

Eu estava usando a solução fornecida pelo @ptman, mas uma alteração recente do servidor deixou de ser viável. Em vez disso, estou usando o seguinte 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 * | ordenar -nr | corte -f2 | xargs du -sh

1
ageek2remember

Aqui está um exemplo

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

Devoluções:

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

Você também pode adicionar | head -10 para encontrar as 10 principais ou qualquer número de subpastas no diretório especificado.

1
ode2k

Este é o alias que tenho no meu perfil.

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

sort -h é o que realmente ajuda aqui à pergunta.

Outras opções úteis são du -x para permanecer no mesmo sistema de arquivos; O Sudo também ajuda a não ver erros se houver diretórios que não sejam legíveis pelo mundo. Além disso, eu sempre faço du --max-depth = 1, depois faço uma busca detalhada, etc.

0
Tagar

Mais um script du!

Como já há muitas respostas, apenas posto meu próprio script lá. Eu uso há mais de oito anos.

Isso poderia ser executado por

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

onde

  • sinalizador opcional -b diga para usar contagem de bytes em vez de bloco contagem
  • opcional caminho como 1º argumento, diretório atual, se o padrão.
  • se nenhum segundo argumento for fornecido, o tamanho mínimo a ser impresso é 256Mb.

A saída pode parecer com:

\___   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
...

Existe o script:

#!/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:-.}"

E não, não vou publicá-las em Git***.xxx.

Você pode mostrá-los lá ou baixar o script lá.

0
F. Hauri

Aqui está minha solução, um script bash simples que chama apenas uma vez e mostra apenas diretórios de tamanho 1 MB ou superior:

#!/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

Pelo menos com as ferramentas usuais, isso será difícil devido ao formato em que os números legíveis por humanos estão (observe que esse tipo faz um "bom trabalho" aqui, pois 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 o contrário - usaria a saída de "du | sort -n -r" e depois converteria os números em formato legível por humanos com algum script ou programa.

0
schnaader

O que você pode tentar é:

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

Espero que ajude.

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

A solução a seguir é semelhante ao original de cadrian, no entanto, isso executará apenas 2 du comandos em vez de um du para cada diretório na árvore.

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

No entanto, a solução da 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

0
Steve Weet

Vagamente baseado na lógica em esta linha , escrevi um script que fornece uma saída du (1) legível por humanos. Além de exigir o -h sinalizador para legibilidade, não requer outros comandos não compatíveis com POSIX.

Está disponível em https://github.com/pleappleappleap/sorted-human-d .

0
Tripp Kinetics

Por que não jogar outro chapéu no ringue ... é uma pergunta antiga, mas aqui está um exemplo que é (principalmente) o script Shell puro (fwiw) - ou seja, apenas bash e nenhum Perl/python/awk/etc. Então, nesse sentido, talvez ele ofereça algo novo à discussão (ou não). Ele calcula o tamanho do arquivo apenas uma vez, mas imprime em várias unidades (minha preferência). (A versão não simplificada inclui getopts que excluem "GB" se indesejados.)

#!/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

Classifica em ordem decrescente.

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