sviluppo-web-qa.it

Come posso ordinare l'output du -h per dimensione

Ho bisogno di ottenere un elenco di output leggibile dall'uomo.

Tuttavia, du non ha un'opzione "ordina per dimensione" e il piping su sort non funziona con il flag leggibile dall'uomo.

Ad esempio, eseguendo:

du | sort -n -r 

Emette un utilizzo del disco ordinato per dimensione (decrescente):

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

Tuttavia, eseguendolo con la bandiera umana leggibile, non si ordina correttamente:

du -h | sort -n -r

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

Qualcuno sa un modo per ordinare du -h per dimensione?

1029
Tom Feiner

A partire da GNU coreutils 7.5 rilasciato nell'agosto 2009, sort consente un parametro -h, Che consente suffissi numerici del tipo prodotto da du -h:

du -hs * | sort -h

Se stai usando un ordinamento che non supporta -h, Puoi installare GNU Coreutils. Ad esempio su un Mac OS X precedente:

brew install coreutils
du -hs * | gsort -h

Da sortmanuale :

-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, un'altra risposta: ordina l'output leggibile da du -h usando un altro strumento. Come 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)}<>;'

Dividi su due righe per adattarsi al display. Puoi usarlo in questo modo o renderlo un one-liner, funzionerà in entrambi i modi.

Produzione:

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

EDIT: Dopo alcune partite di golf a PerlMonks , il risultato finale è il seguente:

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

C'è uno strumento immensamente utile che uso chiamato ncd che è progettato per trovare quelle fastidiose cartelle e file ad alto utilizzo di disco e rimuoverli. È basato su console, veloce e leggero e ha pacchetti su tutte le principali distribuzioni.

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

Per quanto posso vedere, hai tre opzioni:

  1. Modifica du per ordinare prima della visualizzazione.
  2. Modifica sort per supportare le dimensioni umane per l'ordinamento numerico.
  3. Post elabora l'output dall'ordinamento per modificare l'output di base in leggibile.

Puoi anche fare du -k e vivere con taglie in KiB.

Per l'opzione 3 è possibile utilizzare il seguente 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

Ho avuto anche quel problema e attualmente sto usando una soluzione alternativa:

du -scBM | sort -n

Ciò non produrrà valori in scala, ma produrrà sempre la dimensione in megabyte. È meno che perfetto, ma per me è meglio di niente (o visualizza la dimensione in byte).

20
Joachim Sauer

Trovato questo post altrove. Pertanto, questo script Shell farà ciò che vuoi senza chiamare du su tutto due volte. Usa awk per convertire i byte grezzi in un formato leggibile dall'uomo. Naturalmente, la formattazione è leggermente diversa (tutto viene stampato con una precisione decimale).

#/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
}}}'

Eseguendo questo nel mio .vim rese della directory:

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

(Spero che 3,6 milioni di combinazioni di colori non siano eccessive.)

19
Adam Bellaire

Questa versione utilizza awk per creare colonne aggiuntive per le chiavi di ordinamento. Chiama du solo una volta. L'output dovrebbe apparire esattamente come du.

L'ho diviso in più righe, ma può essere ricombinato in una riga.

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

Spiegazione:

  • INIZIA - crea una stringa da indicizzare per sostituire 1, 2, 3 con K, M, G per il raggruppamento per unità, se non c'è unità (la dimensione è inferiore a 1K), allora non c'è corrispondenza e viene restituito uno zero (perfetto! )
  • stampa i nuovi campi - unità, valore (per far funzionare correttamente l'ordinamento alfa è a zero, lunghezza fissa) e linea originale
  • indicizza l'ultimo carattere del campo dimensione
  • estrarre la parte numerica della dimensione
  • ordina i risultati, scarta le colonne extra

Provalo senza il comando cut per vedere cosa sta facendo.

Ecco una versione che esegue l'ordinamento all'interno dello script AWK e non richiede 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]]}'

Ecco un esempio che mostra le directory in una forma riepilogativa più compatta. Gestisce gli spazi nella directory/nomi dei file.

% 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

ordina i file per dimensione in MB

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

Ho un semplice ma utile python per du chiamato dutop . Nota che noi (i manutentori di coreutils) stiamo valutando di aggiungere la funzionalità per ordinare per ordinare "umano" uscita diretta.

9
pixelbeat

Ne ho un altro:

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

Sto iniziando ad apprezzare Perl. Potrebbe essere necessario fare un

$ cpan Number::Bytes::Human

primo. A tutti gli hacker Perl là fuori: Sì, so che la parte di ordinamento può essere eseguita anche in Perl. Probabilmente anche la seconda parte.

9
0x89

Questo frammento è stato sfacciato senza vergogna da 'Jean-Pierre' da http://www.unix.com/Shell-programming-scripting/32555-du-h-sort.html . C'è un modo in cui posso dargli credito?

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

Usa il flag "-g"

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

E sulla mia directory/usr/local produce output in questo modo:

$ 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

Trovato questo online ... sembra funzionare bene

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

Ecco il semplice metodo che utilizzo, un utilizzo delle risorse molto basso e ti offre ciò di cui hai bisogno:

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

Ieri ho imparato a meravigliare inventando questo esempio. Ci è voluto del tempo, ma è stato molto divertente e ho imparato a usare awk.

Funziona solo du una volta e ha un output molto simile 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 numeri inferiori a 10 con un punto decimale.

4
marlar

Un altro:

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 | ordina -rn | testa -10 | awk '{print ($ 1)/1024, "MB", $ 2'}

3
Patrick

Se è necessario gestire gli spazi, è possibile utilizzare quanto segue

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

L'istruzione sed aggiuntiva aiuterà ad alleviare i problemi con le cartelle con nomi come Supporto applicazioni

2
Chealion

Ecco:

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

Ci sono molte risposte qui, molte delle quali sono duplicati. Vedo tre tendenze: passare in rassegna un secondo du call, usare un complicato codice Shell/awk e usare altre lingue.

Ecco una soluzione conforme POSIX che utilizza d e awk che dovrebbe funzionare su ogni sistema.

Ho adottato un approccio leggermente diverso, aggiungendo -x Per assicurarmi di rimanere sullo stesso filesystem (ho sempre bisogno di questa operazione quando ho poco spazio su disco, quindi perché eliminare le cose che ho montato dentro this FS o spostato e ricollegato indietro?) e visualizzazione di unità costanti per facilitare l'analisi visiva. In questo caso, in genere scelgo no per ordinare Posso vedere meglio la struttura gerarchica.

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

(Dato che questo è in unità coerenti, puoi quindi aggiungere | sort -n Se vuoi davvero ordina ed i risultati.)

Ciò filtra qualsiasi directory il cui contenuto (cumulativo) non superi i 512 MB e quindi visualizza le dimensioni in gigabyte. Di default, du usa una dimensione di blocco di 512 byte (quindi la condizione di awk è 220 blocchi è 512 MB e i suoi 221 divisor converte le unità in GB - potremmo usare du -kx con $1 > 512*1024 e s/1024^2 per essere più leggibili dall'uomo). All'interno della condizione awk, impostiamo s sulla dimensione in modo da poterlo rimuovere dalla riga ($0). Ciò mantiene il delimitatore (che è compresso in un singolo spazio), quindi il %s Finale rappresenta uno spazio e quindi il nome della directory aggregata. %7s Allinea la dimensione arrotondata %.2f GB (aumenta a %8s Se hai> 10 TB).

A differenza della maggior parte delle soluzioni qui, questo supporta correttamente le directory con spazi nei loro nomi (sebbene ogni soluzione, incluso questo uno, gestirà in modo errato i nomi delle directory contenenti le interruzioni di riga).

1
Adam Katz

Un'altra soluzione 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

Navigazione della directory, ordinamento (nome e dimensioni), rappresentazione grafica, lettura umana, ecc ...

1
Adam Eickhoff

Stavo usando la soluzione fornita da @ptman, ma una recente modifica del server l'ha resa non più praticabile. Invece, sto usando il seguente 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 * | ordina -nr | cut -f2 | xargs du -sh

1
ageek2remember

Ecco un esempio

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

Ritorna:

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

Puoi anche aggiungere | head -10 per trovare la top 10 o un numero qualsiasi di sottocartelle nella directory specificata.

1
ode2k

Questo è l'alias che ho nel mio .profile

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

sort -h è ciò che aiuta davvero qui alla domanda posta.

Altre opzioni utili sono du -x per rimanere sullo stesso filesystem; anche Sudo aiuta a non vedere errori se ci sono directory che non sono leggibili dal mondo. Inoltre, faccio sempre du --max-depth = 1, quindi analizzo ulteriormente, ecc.

0
Tagar

Ancora un altro script du!

Dato che c'è già molta risposta, ho appena pubblicato la mia sceneggiatura lì. Uso da più di otto anni ormai.

Questo potrebbe essere gestito da

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

dove

  • flag opzionale -b indica di utilizzare conteggio byte invece di conteggio blocchi
  • facoltativo percorso come primo argomento, directory corrente se predefinita.
  • se non viene fornito alcun secondo argomento, la dimensione minima da stampare è 256Mb.

L'output potrebbe apparire come:

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

C'è lo 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 no, non li posterò su Git***.xxx.

È possibile mostrarli lì o scaricare lo script lì.

0
F. Hauri

Ecco la mia soluzione, un semplice script bash che chiama du solo una volta e ti mostra solo directory di dimensioni pari o superiori a 1 MB:

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

Almeno con i soliti strumenti, questo sarà difficile a causa del formato in cui si trovano i numeri leggibili dall'uomo (nota che l'ordinamento fa un "buon lavoro" qui in quanto ordina i numeri - 508, 64, 61, 2, 2 - esso semplicemente non riesco a ordinare i numeri in virgola mobile con un moltiplicatore aggiuntivo).

Ci proverei al contrario: utilizzare l'output di "du | sort -n -r" e successivamente convertire i numeri in formato leggibile dall'uomo con qualche script o programma.

0
schnaader

Quello che puoi provare è:

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

Spero che aiuti.

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 seguente soluzione è simile all'originale di Cadrian, tuttavia questo eseguirà solo 2 du comandi invece di un du per ogni directory nella struttura.

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

Tuttavia la soluzione di Cardrian è più solida in quanto quanto sopra non funzionerà per alberi molto popolati in quanto potrebbe superare il limite sulla dimensione degli argomenti passati a du

0
Steve Weet

Liberamente basato sulla logica in questo one-liner , ho scritto uno script che fornisce un output du (1) leggibile dall'uomo. Oltre a richiedere il -h flag per leggibilità umana, non richiede altri comandi non compatibili con POSIX.

È disponibile su https://github.com/pleappleappleap/sorted-human-d .

0
Tripp Kinetics

Perché non gettare un altro cappello sul ring ... è una vecchia domanda, ma ecco un esempio che è (per lo più) puro script di Shell (prima guerra mondiale) - cioè solo bash e nessun Perl/python/awk/etc. Quindi, in tal senso, forse offre qualcosa di nuovo alla discussione (o no). Calcola la dimensione del file solo una volta, ma stampa in varie unità (la mia preferenza). (La versione non semplificata include getopts che esclude "GB" se non desiderato.)

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

Ordina in ordine decrescente.

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