Jak mogę posortować dane wyjściowe du-h według rozmiaru


966

Muszę uzyskać listę czytelnych dla człowieka wyników.

Nie duma jednak opcji „sortuj według rozmiaru”, a przesyłanie do sortnie działa z flagą czytelną dla człowieka.

Na przykład uruchamianie:

du | sort -n -r 

Zwraca posortowane użycie dysku według rozmiaru (malejąco):

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

Jednak uruchomienie go z flagą czytelną dla człowieka nie sortuje poprawnie:

du -h | sort -n -r

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

Czy ktoś zna sposób sortowania du -h według rozmiaru?


Hej ... Zabawne, że powinieneś zapytać, ponieważ denerwuje mnie to ... od ponad roku. W zeszłym tygodniu pobrałem kod do GNU coreutils (którego część jest częścią) i spojrzałem, ale zdecydowałem, że załatanie zajmie mi trochę więcej czasu niż na rękach ... Ktoś? :)
zrelaksuj się

Oto bardzo powiązane pytanie: serverfault.com/q/737537/35034
cregox

Widziałeś to? unix.stackexchange.com/questions/4681/... Jest prawie duplikatem i jest wart złota. Robisz normalnie, duale dodajesz -h do sortpolecenia. Możesz dodać, -rhaby największe były pierwsze w pliku, w przeciwnym razie musisz tailzobaczyć kosmiczne świnie.
SDsolar,

Nie spodziewałem się, że takie pytanie stanie się tak popularne, gdy go przejdę.
Mateen Ulhaq

Odpowiedzi:


1360

Począwszy od wersji GNU coreutils 7.5 wydanej w sierpniu 2009 r., sortDopuszcza -hparametr, który dopuszcza sufiksy numeryczne, takie jak du -h:

du -hs * | sort -h

Jeśli używasz systemu, który nie obsługuje -h, możesz zainstalować GNU Coreutils. Np. Na starszym Mac OS X:

brew install coreutils
du -hs * | gsort -h

Z sort instrukcji :

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


3
Odpowiednia sekcja podręcznika: gnu.org/software/coreutils/manual/…
wodow

29
Łatwy do zainstalowania w systemie OS X z Homebrew - instaluj coreutils do parzenia.
Richard Poirier

41
Dobry! Osobiście zawsze robiłem to du -BM | sort -nrjako obejście - jest wystarczająco czytelne dla ludzi i jest sortowane, jeśli ktoś utknie ze starszymi rdzeniami.
chutz

30
Jeśli używasz w OSX przez Homebrew, pamiętaj, że będziesz teraz musiał używać gsort zamiast sortować:du -hs * | gsort -h
Brian Cline

2
@PaulDraper, du -BMdrukuje wszystko w megabajtach, więc plik o wielkości 168 KB byłby wyświetlany jako 0 MB. Chyba że istnieje jakaś inna rozbieżność wersji, o której nie wiem. Moja wersja dupokazuje tylko wartości całkowite megabajtów.
chutz

88
du | sort -nr | cut -f2- | xargs du -hs

48
I zrobi ogromną liczbę zduplikowanych liczeń.
Douglas Leeder,

1
Najpierw wykonuje normalny du - następnie dla każdego wpisu ponownie oblicza rozmiar, aby wydrukować go w czytelnej dla człowieka formie.
Douglas Leeder,

8
@Douglas Leeder: masz prawo do liczenia duplikatów, ale pomyśl, że drugi du nie zaczyna się od zimnej pamięci podręcznej (dzięki systemowi operacyjnemu) @hasen j: xargs to bardzo przydatne polecenie, dzieli swoje standardowe wejście i podaje je jako argumenty do podanego polecenia
cadrian

4
Chris jest tak naprawdę lepszy, ponieważ działa ze ścieżkami zawierającymi spacje. Głosujesz po swojemu, kolego.
rbright

3
Brzydkie, ale wieloplatformowe :).
voretaq7,

62

@Douglas Leeder, jeszcze jedna odpowiedź: posortuj dane wyjściowe czytelne dla człowieka z du-h za pomocą innego narzędzia. Jak 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)}<>;'

Podziel na dwie linie, aby dopasować do wyświetlacza. Możesz użyć go w ten sposób lub uczynić z niego jedno-liniowego, będzie działał w obu kierunkach.

Wynik:

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

EDYCJA: Po kilku rundach golfa w PerlMonks końcowy wynik jest następujący:

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

2
Twoja krótka wersja jest włączana, stderrponieważ diemożesz ją zmienić, aby włączała się stdout?
Dennis Williamson,

2
Zmień na diea, printa przejdzie do stdout. To tylko dwie kolejne postacie.
Adam Bellaire,

działa na ubuntu!
marinara,

imponująca perl hackistry
nandoP

Wynik jest w odwrotnej kolejności :(
RSFalcon7

55

Istnieje niezmiernie użyteczne narzędzie, którego używam, o nazwie ncdu, które zostało zaprojektowane do znajdowania tych irytujących folderów i plików o wysokim zużyciu dysku oraz ich usuwania. Jest oparty na konsoli, szybki i lekki, i ma pakiety we wszystkich głównych dystrybucjach.


Bardzo fajnie ... Zastanawiam się, czy wyniki można by podać na standardowe wyjście ... Jestem tak leniwy, że nie mogę przeczytać instrukcji
ojblass

8
gt5 jest w tym samym stylu; jego funkcja zabójcy wykazuje wzrost.
Tobu,

1
To jest naprawdę fajne! I znacznie szybciej niż wałęsanie się du, jeśli chcesz tylko zidentyfikować duże katalogi.
BurninLeo,

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

Nie można używać z du -k --total, daje błąd na końcudu: cannot access 'total': No such file or directory
laggingreflex

podoba mi się jeszcze jedna odpowiedź. jak byś pokazał tylko pierwsze 50 wyników?
Mau

1
@Mauro - po prostu potokuj wynik head, dodając `| głowa -50` na końcu.
Samuel Lelièvre,

21

O ile widzę, masz trzy opcje:

  1. Zmień, duaby posortować przed wyświetleniem.
  2. Zmień, sortaby obsługiwać ludzkie rozmiary dla sortowania numerycznego.
  3. Przetwarzaj dane wyjściowe z sortowania, aby zmienić podstawowe dane wyjściowe na czytelne dla człowieka.

Możesz także robić du -ki żyć z rozmiarami w KiB.

Dla opcji 3 możesz użyć następującego skryptu:

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

20

Też miałem ten problem i obecnie używam obejścia:

du -scBM | sort -n

Nie spowoduje to wygenerowania skalowanych wartości, ale zawsze da rozmiar w megabajtach. To mniej niż idealne, ale dla mnie to lepsze niż nic (lub wyświetlanie rozmiaru w bajtach).


Podoba mi się przełącznik th -BM, który jest w zasadzie taki sam jak -m, ale ma tę zaletę, że wyświetla na nim rozmiar i literę M, więc dostajesz 10M, co jest znacznie wyraźniejsze niż tylko 10 :)
Tom Feiner

To najprostsze rozwiązanie, jakie do tej pory widziałem na tej stronie, dziękuję!
Jeff Olson,

19

Znalazłem ten wpis gdzie indziej. Dlatego ten skrypt powłoki zrobi, co chcesz, bez wywoływania duwszystkiego dwa razy. Służy awkdo konwersji nieprzetworzonych bajtów na format czytelny dla człowieka. Oczywiście formatowanie jest nieco inne (wszystko jest drukowane z dokładnością do jednego miejsca po przecinku).

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

Uruchomienie tego w moim .vimkatalogu daje:

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

(Mam nadzieję, że 3,6 mln schematów kolorów nie jest nadmierne).


1
Mam też odpowiedź w języku Perl, ale myślę, że może mnie to znienawidzić: du -B1 | sort -nr | perl -e '% h = (0 => b, 1 => K, 2 => M, 3 => G); for (<>) {($ s, @ f) = split / \ s + /; $ e = 3; $ e-- while (1024 ** $ e> $ s); $ v = ($ s / (1024 ** $ e)); printf "% -8s% s \ n", sprintf ($ v> = 100? "% d% s": "% .1f% s", $ s / (1024 ** $ e), $ h {$ e}), @ f;} '
Adam Bellaire

Mimo że odpowiedź Perla w rzeczywistości znacznie bardziej przypomina formatowanie. Chociaż zaokrąglanie jest wyłączone ... Wygląda na to, że du zawsze daje ceil () niż round ()
Adam Bellaire

Hej, dlaczego tam użyłem skrótu? Gdyby byli tablicą ... rano-mózg narzekać ....
Adam BELLAIRE

Dodano lepsze rozwiązanie Perla jako kolejną odpowiedź.
Adam Bellaire,

Obie wersje zawodzą, gdy nazwy plików zawierają spacje
Vi.

15

Ta wersja używa awkdo tworzenia dodatkowych kolumn dla kluczy sortowania. Dzwoni tylko duraz. Wynik powinien wyglądać dokładnie tak du.

Podzieliłem go na wiele linii, ale można go zrekombinować w jedną linijkę.

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

Wyjaśnienie:

  • ROZPOCZNIJ - utwórz ciąg do indeksowania, aby podstawić 1, 2, 3 dla K, M, G dla grupowania według jednostek, jeśli nie ma żadnej jednostki (rozmiar jest mniejszy niż 1K), to nie ma dopasowania i zwracane jest zero (idealnie! )
  • wydrukuj nowe pola - jednostka, wartość (aby sortowanie alfanumeryczne działało poprawnie, to jest wypełniony zerami, o stałej długości) i linia oryginalna
  • zindeksuj ostatni znak pola rozmiaru
  • wyciągnij część liczbową rozmiaru
  • posortuj wyniki, odrzuć dodatkowe kolumny

Wypróbuj bez cutpolecenia, aby zobaczyć, co robi.

Oto wersja, która sortuje w skrypcie AWK i nie potrzebuje 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]]}'

Dziękuję Ci! to jest pierwszy przykład, który działa dla mnie w OS X 10.6, nie licząc skryptów perl / phython. i jeszcze raz dziękuję za dobre wyjaśnienie. zawsze miło jest nauczyć się czegoś nowego. awk na pewno jest potężnym narzędziem.
Wolf

Wielkie dzięki za to. Zmieniłem du, aby du -sh *wyświetlał tylko bezpośrednie pliki i katalogi bez rekurencyjnego zejścia.
HankCa,

15

Oto przykład, który pokazuje katalogi w bardziej zwięzłej, podsumowanej formie. Obsługuje spacje w nazwach katalogów / plików.

% 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

1
Użytkownicy systemu macOS / OSX powinni zostać ostrzeżeni, że wersja Mac xargs nie obsługuje flagi -d, a jeśli ją pominiesz, w każdym katalogu zawierającym spację każde słowo zostanie przeanalizowane oddzielnie, co oczywiście nie powiedzie się.
jasonology

11

sortuj pliki według rozmiaru w MB

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

9

Mam proste, ale przydatne opakowanie Pythona dla du o nazwie dutop . Zauważ, że my (opiekunowie coreutils) rozważamy dodanie funkcji sortowania w celu bezpośredniego sortowania wyników „ludzkich”.


1
+1 za jeden z rzadkich, ważnych wyjątków, aby „zrobić jedną rzecz i zrobić to dobrze”. Chyba że ktoś zrozumie prefiks SI i / lub prefiksy binarne.
Joachim Sauer

I jak wspomina ptman poniżej: ta da ! (nowa sortflaga)
Tobu

9

Mam jeszcze jeden:

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

Zaczynam lubić Perla. Być może będziesz musiał zrobić

$ cpan Number::Bytes::Human

pierwszy. Do wszystkich hakerów Perla: Tak, wiem, że część sortowania można również wykonać w Perlu. Prawdopodobnie też część du.


8

Fragment ten został bezwstydnie wciągnięty w „Jean-Pierre” z http://www.unix.com/shell-programming-scripting/32555-du-h-sort.html . Czy jest sposób, w jaki mogę go lepiej przypisać?

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;
     }
    '

myślę, że jeśli jest to bardzo duża liczba, oznacza to, że jednostka zniknęła, a wyświetlana liczba jest mała ... spróbuj23423423432423
nopole

7

Użyj flagi „-g”

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

A mój katalog / usr / local tworzy dane wyjściowe w następujący sposób:

$ 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

4
Nie daje to jednak czytelnego dla człowieka wyniku, czego szukał OP.

4

Inny:

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

Oto prosta metoda, której używam, bardzo niskie zużycie zasobów i zapewnia to, czego potrzebujesz:

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

Znaleziono ten on-line ... wydaje się działać 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

Luźno bazując na tym jednowierszowym, stworzyłem skrypt zapewniający czytelne dla człowieka, posortowane wyjście du (1). Proszę odnieść się do mojej odpowiedzi, serverfault.com/a/937459/218692 .
Tripp Kinetics

3

Nauczyłem się awk od wymyślania tego przykładu wczoraj. Zajęło to trochę czasu, ale była świetna zabawa i nauczyłem się korzystać z awk.

Działa tylko du raz i ma wyjście bardzo podobne do 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 }'

Pokazuje liczby poniżej 10 z jednym miejscem po przecinku.


3

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


2

Jeśli potrzebujesz obsługiwać spacje, możesz użyć następujących

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

Dodatkowa instrukcja sed pomoże złagodzić problemy z folderami o nazwach takich jak obsługa aplikacji


Właśnie wypróbowałem to na macOS Sierra. Działa zgodnie z oczekiwaniami. Miły!
jasonology

1

Voilà:

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

1

http://dev.yorhel.nl/ncdu

polecenie: ncdu

Nawigacja w katalogu, sortowanie (nazwa i rozmiar), tworzenie wykresów, czytelność dla człowieka itp.


1
Świetne narzędzie, ale domyślnie nie instalowane w żadnym znanym systemie operacyjnym. Niekoniecznie problem, ale jeszcze jeden program, którym trzeba się
zająć

1

Inne awkrozwiązanie -

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

Korzystałem z rozwiązania dostarczonego przez @ptman, ale ostatnia zmiana serwera sprawiła, że ​​nie jest już wykonalny. Zamiast tego używam następującego skryptu 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);
}'

du -d 1Składnia BSD jest obsługiwana przez GNU du od czasu wydania coreutils 8.6 w 2010 r. (Chociaż jego pierwsza dostępność Red Hat to RHEL 7 w 2014 r.), Więc nie jest już potrzebny --maxdepth=1. I tylko dowiedział się o tym niedawno sam.
Adam Katz


1

Tutaj jest wiele odpowiedzi, z których wiele jest duplikatami. Widzę trzy trendy: przepuszczanie drugiego wywołania du, używanie skomplikowanego kodu powłoki / awk i używanie innych języków.

Oto rozwiązanie zgodne z POSIX, wykorzystujące du i awk, które powinno działać na każdym systemie.

Podjąłem nieco inne podejście, dodając, -xaby upewnić się, że pozostajemy w tym samym systemie plików (potrzebuję tej operacji tylko wtedy, gdy brakuje mi miejsca na dysku, więc dlaczego usuwamy rzeczy, które zamontowałem w tym drzewie FS lub przeniosłem i symlinked back?) i wyświetlanie stałych jednostek, aby ułatwić wizualną analizę. W takim przypadku zazwyczaj nie sortuję, aby lepiej widzieć strukturę hierarchiczną.

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

(Ponieważ jest to spójne jednostki, możesz następnie dołączyć, | sort -njeśli naprawdę chcesz posortować wyniki).

Spowoduje to odfiltrowanie dowolnego katalogu, którego (skumulowana) zawartość nie przekracza 512 MB, a następnie wyświetla rozmiary w gigabajtach. Standardowo stosuje du 512-bajtowy rozmiar bloku (czyli stan awk 2 20 bloków jest 512 oraz jej 2 21 dzielnik przetwarza jednostki z GB - można było skorzystać du -kxz $1 > 512*1024i s/1024^2do bardziej czytelnej dla człowieka). Wewnątrz warunku awk ustawiamy srozmiar, abyśmy mogli go usunąć z linii ( $0). Zachowuje to separator (zwinięty do pojedynczej spacji), więc finał %sreprezentuje spację, a następnie nazwę zagregowanego katalogu. %7swyrównuje zaokrąglony %.2frozmiar GB (zwiększ, %8sjeśli masz> 10 TB).

W przeciwieństwie do większości rozwiązań tutaj, to poprawnie obsługuje katalogi ze spacjami w nazwach (chociaż każde rozwiązanie, w tym jedno, będzie źle traktować nazwy katalogów zawierające podziały wierszy).


0

Przynajmniej w przypadku zwykłych narzędzi będzie to trudne ze względu na format, w jakim znajdują się liczby czytelne dla człowieka (zauważ, że sort wykonuje tutaj „dobrą robotę”, ponieważ sortuje liczby - 508, 64, 61, 2, 2 - it po prostu nie można sortować liczb zmiennoprzecinkowych za pomocą dodatkowego mnożnika).

Spróbowałbym odwrotnie - użyj danych wyjściowych z "du | sort -n -r", a następnie przekonwertuj liczby na format czytelny dla człowieka za pomocą jakiegoś skryptu lub programu.


0

Możesz spróbować:

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

Mam nadzieję, że to pomaga.


właśnie to robi xargs ;-)
cadrian

hehe, zawsze zapominam o xargs. ;) Pod koniec dnia cokolwiek wykonuje pracę imo.

MacOSX domyślnie (tj. Poza home-brewem) nie obsługuje właściwego, xargswięc ten formularz był konieczny. Jednak w przypadku plików ze spacjami należy ustawić IFS:IFS=$'\n'
HankCa

0
du | sort -nr | awk '{ cmd = "du -h -d0 "$2"| cut -f1"; cmd | getline human; close(cmd); print human"\t"$2 }'
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.