1418

I need to get a list of human readable du output.

However, du does not have a "sort by size" option, and piping to sort doesn't work with the human readable flag.

For example, running:

du | sort -n -r 

Outputs a sorted disk usage by size (descending):

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

However, running it with the human readable flag, does not sort properly:

du -h | sort -n -r

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

Does anyone know of a way to sort du -h by size?

Tom Feiner
  • 17,578
  • 8
  • 30
  • 24
  • Here's a much related question: http://serverfault.com/q/737537/35034 – cregox Nov 19 '15 at 14:15
  • Have you seen this one? https://unix.stackexchange.com/questions/4681/how-do-you-sort-du-output-by-size It is a near duplicate and is worth gold. You do a normal `du` but add the -h to the `sort` command. You can add `-rh` so the largest are first in the file, otherwise you need `tail` to see the space hogs. – SDsolar Aug 17 '17 at 08:32
  • See also https://superuser.com/questions/300606/how-to-analyse-disk-usage-in-command-line-linux for a friendlier alternative (`ncdu`). – Cees Timmerman May 10 '21 at 23:29
  • Also [Tracking down where disk space has gone on Linux?](https://unix.stackexchange.com/q/125429) – Henke Dec 02 '22 at 10:53
  • `du -sh * | sort -h -r` – Code42 Apr 18 '23 at 09:51

39 Answers39

2008

As of GNU coreutils 7.5 released in August 2009, sort allows a -h parameter, which allows numeric suffixes of the kind produced by du -h:

du -hs * | sort -h

If you are using a sort that does not support -h, you can install GNU Coreutils. E.g. on an older Mac OS X:

brew install coreutils
du -hs * | gsort -h

From sort manual:

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

ptman
  • 28,394
  • 2
  • 30
  • 45
  • 4
    The relevant section of the manual: http://www.gnu.org/software/coreutils/manual/coreutils.html#sort-invocation – wodow Feb 09 '11 at 11:13
  • 32
    Easy to install on OS X with homebrew -- brew install coreutils. – Richard Poirier May 01 '11 at 18:53
  • 1
    wow, thanks. Much better thank my evergreen `du -sk * | sort -n` – ThorstenS Dec 22 '11 at 07:13
  • 50
    Good one! I personally always did `du -BM | sort -nr` as a workaround - it is human readable enough, and it is sorted, if anyone is stuck with older coreutils. – chutz May 24 '12 at 09:06
  • 32
    If using on OSX via Homebrew, note that you'll now need to use gsort rather than sort: `du -hs * | gsort -h` – Brian Cline Dec 16 '13 at 08:45
  • @chutz, that puts `168K` *before* `104M`. – Paul Draper Feb 01 '14 at 08:41
  • 2
    @PaulDraper, `du -BM` prints everything in megabytes, so a file that is 168K would actually display as 0M. Unless there is some other version discrepancy I am not aware of. My version of `du` only shows integer megabyte values. – chutz Feb 01 '14 at 15:12
  • @chutz, yes. `du -sBM * | sort -nr` does work. – Paul Draper Feb 01 '14 at 18:18
  • You can install the GNU coreutils using MacPorts as described [here](http://tunafreedolphin.com/?p=416]. – jvriesem Oct 13 '14 at 20:49
  • I [installed coreutils on CentOS for sort --human-readable flag but it still doesn't work](http://unix.stackexchange.com/questions/176893/installed-coreutils-on-centos-for-sort-human-readable-flag-but-it-still-doesn) – laggingreflex Jan 01 '15 at 01:03
  • If using on FreeBSD, try gsort instead sort. – Vladislav Jul 21 '15 at 02:26
  • The way `sort -h` seems to work is to sort by the suffix first, and then by the numeric value. e.g. 2000 is deemed to be less than 1K. This would be fine in most autogenerated listings though, where a smaller number will never have a larger suffix then a larger number. – mwfearnley Sep 24 '15 at 07:46
  • Standard `du` on OS X does not support the suggested options, but the one from coreutils does (`gdu`) `gdu -hs * | gsort -h` – pojo Sep 02 '16 at 12:34
  • 1
    The [du(1) man page on Mac OS X 10.9](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/du.1.html) claims that du supports -h – ptman Sep 02 '16 at 12:45
  • 1
    For future Google users like myself, if you want to use this answer's command but sort by size descending instead of ascending, you just need the `-r` option for `size`. To scroll a list of the largest stuff, use `du -hs * | sort -hr | less`. – Mike Turley Feb 25 '18 at 17:20
  • This solution does not work on hidden directories that start with a "." like ".git" – giorgio79 May 22 '18 at 18:15
  • 1
    @giorgio79 in that case, use `* .??*` – ptman May 22 '18 at 19:33
  • 2
    I use `du -sh ./* | sort -g` cause `-h` is not supported on BusyBox v1.27.2 – vladkras May 23 '18 at 12:05
  • I like to show the top ten sorted largest to smallest with `du -sh * | sort -h -r | head -n 10` – Selwyn Polit Jan 18 '19 at 17:50
  • 2
    Simpler: `du -h | sort -h` – Marco Marsala Mar 22 '19 at 07:31
  • For me, `sort` itself already has that feature. `gsort` is not pre-installed. – neverMind9 Aug 01 '19 at 17:15
  • 1
    What is the best practice between `du -hs *` and `du -h -d1`? – baptx May 19 '20 at 09:24
  • 1
    @baptx They're different things. Do you want dotfiles or not? – ptman May 19 '20 at 09:57
  • @ptman thanks, indeed I want to see everything, including files and folders starting with a dot but `du -hs *` did not display them. In this case, you should add to your answer that we have to use `du -h -d1`. – baptx May 19 '20 at 10:27
  • Add the -r option to sort in descending order as in " du -sh * | sort -hr" – David Okwii Apr 30 '21 at 16:52
  • 1
    highly recommend using `du -chxd 1` rather than summary. it's much more informative! – cregox Jul 10 '21 at 02:33
  • If I'm in a directory and I want to list the files in reverse size order I do `du -h | sort -rh` – Wadih M. Dec 10 '21 at 19:24
  • For hidden directories with zsh, I suggest `du -hs *(D) | sort -h` – Ulysse BN Nov 09 '22 at 00:07
109
du | sort -nr | cut -f2- | xargs du -hs
cadrian
  • 1,305
  • 2
  • 8
  • 13
  • 59
    And it'll do a huge amount of duplicate counting. – Douglas Leeder Feb 25 '09 at 13:55
  • it would help if you explain why that works?? – hasen Feb 25 '09 at 14:10
  • 1
    First it does the normal du - then for each entry it recalculates the size just to print it in human readable form. – Douglas Leeder Feb 25 '09 at 14:22
  • 8
    @Douglas Leeder: you are right for the duplicate counting, but think that the second du does not start from cold cache (thanks to the OS) @hasen j: xargs is a very useful command, it splits its stdin and feeds it as arguments to the given command – cadrian Feb 25 '09 at 14:52
  • Don't really care about reputation score, but I am a bit confused as to why this answer has 12 votes when my more or less identical answer below has none. –  Feb 25 '09 at 20:46
  • 4
    Chris's is actually superior since it works with paths containing whitespace. Throwing a vote your way, buddy. – rbright Feb 25 '09 at 22:45
  • Two reasons: most folks just vote for the first good answer they see, and secondly, many people don't know what the -k option to du does. – Michael Kohne Sep 02 '09 at 19:52
  • 3
    Ugly, but cross-platform :). – voretaq7 Nov 29 '11 at 23:06
85

There is an immensely useful tool I use called ncdu that is designed for finding those pesky high disk-usage folders and files, and removing them. It's console based, fast and light, and has packages on all the major distributions.

  • Very nice... I wondier if the results could be fed to standard out... I am so lazy that I cannot read the manual – ojblass Jun 27 '09 at 05:17
  • 8
    [gt5](http://gt5.sourceforge.net/) is in the same vein; its killer feature is displaying growth. – Tobu Jul 01 '10 at 16:16
  • 2
    That's really cool! And much faster than hanging around with `du`, if you just want to identify the large directories. – BurninLeo Sep 16 '15 at 17:49
70

@Douglas Leeder, one more answer: Sort the human-readable output from du -h using another tool. Like 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)}<>;'

Split onto two lines to fit the display. You can use it this way or make it a one-liner, it'll work either way.

Output:

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

EDIT: After a few rounds of golf over at PerlMonks, the final result is the following:

perl -e'%h=map{/.\s/;99**(ord$&&7)-$`,$_}`du -h`;die@h{sort%h}'
Adam Bellaire
  • 1,190
  • 1
  • 7
  • 10
47
du -k * | sort -nr | cut -f2 | xargs -d '\n' du -sh
Jake Wilson
  • 8,814
  • 29
  • 97
  • 125
24

As far as I can see you have three options:

  1. Alter du to sort before display.
  2. Alter sort to support human sizes for numerical sort.
  3. Post process the output from sort to change the basic output to human readable.

You could also do du -k and live with sizes in KiB.

For option 3 you could use the following 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
Douglas Leeder
  • 2,745
  • 18
  • 15
24

I've had that problem as well and I'm currently using a workaround:

du -scBM | sort -n

This will not produce scaled values, but always produce the size in megabytes. That's less then perfect, but for me it's better than nothing (or displaying the size in bytes).

Joachim Sauer
  • 840
  • 5
  • 19
  • I like th -BM switch, which is basically the same as -m, but it has the advantage of displaying the size and M postfixed to it, so you get 10M which is much clearer than just 10 :) – Tom Feiner Feb 25 '09 at 14:02
  • This is the simplest solution I've seen so far on this page, thank you! – Jeff Olson Nov 05 '15 at 16:35
21

Found this posting elsewhere. Therefore, this shell script will do what you want without calling du on everything twice. It uses awk to convert the raw bytes to a human-readable format. Of course, the formatting is slightly different (everything is printed to one decimal place precision).

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

Running this in my .vim directory yields:

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

(I hope 3.6M of color schemes isn't excessive.)

Adam Bellaire
  • 1,190
  • 1
  • 7
  • 10
  • 3
    I have a Perl answer, too, but I think it might make people hate me: 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 Feb 25 '09 at 14:40
  • Even though the Perl answer actually gives its formatting much closer to du. Although the rounding is off... It looks like du always gives ceil() rather than round() – Adam Bellaire Feb 25 '09 at 14:41
  • Hey, why did I use a hash there? Should've been an array... morning-brain *grumble*.... – Adam Bellaire Feb 25 '09 at 15:33
  • Added a better Perl solution as another answer. – Adam Bellaire Feb 25 '09 at 21:06
  • Both versions fail when filenames contain spaces – Vi. Nov 02 '10 at 17:54
20

Here's an example that shows the directories in a more compact summarized form. It handles spaces in directory/filenames.

% 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
slm
  • 7,615
  • 16
  • 56
  • 76
  • 1
    macOS/OSX users be warned that the mac version of xargs doesn’t support the -d flag, and if you omit it, any directories that contain a space have each word parsed separately which of course fails. – jasonology Jul 19 '17 at 04:40
20

This version uses awk to create extra columns for sort keys. It only calls du once. The output should look exactly like du.

I've split it into multiple lines, but it can be recombined into a one-liner.

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

Explanation:

  • BEGIN - create a string to index to substitute 1, 2, 3 for K, M, G for grouping by units, if there's no unit (the size is less than 1K), then there's no match and a zero is returned (perfect!)
  • print the new fields - unit, value (to make the alpha-sort work properly it's zero-padded, fixed-length) and original line
  • index the last character of the size field
  • pull out the numeric portion of the size
  • sort the results, discard the extra columns

Try it without the cut command to see what it's doing.

Here's a version which does the sorting within the AWK script and doesn't need 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]]}'
Dennis Williamson
  • 62,149
  • 16
  • 116
  • 151
  • thank you! this is the first example that works for me in OS X 10.6 not counting the perl/phython-scripts. and thanks again for the good explanation. always nice to learn something new. awk sure is a powerful tool. – Wolf May 04 '11 at 12:09
  • Great thanks for that. I changed the du to `du -sh *` to show just the immediate files and directories without recursive descent. – HankCa Dec 09 '16 at 22:01
16

sort files by size in MB

du --block-size=MiB --max-depth=1 path | sort -n
Mark Henderson
  • 68,823
  • 31
  • 180
  • 259
lukmansh
  • 1
  • 1
  • 3
11

I've a simple but useful python wrapper for du called dutop. Note that we (the coreutils maintainers) are considering adding the functionality to sort to sort "human" output directly.

pixelbeat
  • 256
  • 1
  • 3
  • 1
    +1 for one of the rare, valid exceptions to "do one thing and do it right". Unless someone gets sort to understand the SI-prefix and/or the binary prefixes. – Joachim Sauer Mar 18 '09 at 22:20
  • And as ptman mentions below: [ta da](http://article.gmane.org/gmane.comp.gnu.core-utils.announce/52)! (new `sort` flag) – Tobu Jul 01 '10 at 16:13
11

Got another one:

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

I'm starting to like perl. You might have to do a

$ cpan Number::Bytes::Human

first. To all the perl hackers out there: Yes, I know that the sort part can also be done in perl. Probably the du part, too.

0x89
  • 6,465
  • 3
  • 22
  • 14
10

This snippet was shameless snagged from 'Jean-Pierre' from http://www.unix.com/shell-programming-scripting/32555-du-h-sort.html. Is there a way I can better credit him?

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;
     }
    '
Bozojoe
  • 637
  • 1
  • 6
  • 17
  • i think if it is a very big number, then the unit is gone and the number displayed is small... try `23423423432423` – nonopolarity Apr 22 '15 at 09:18
9

Use the "-g" flag

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

And on my /usr/local directory produces output like this:

$ 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
Mick T
  • 129
  • 4
  • 5
    That doesn't give the human-readable output, though, which is what the OP was looking for. –  Feb 25 '09 at 17:24
7

Found this one on line... seems to work 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
Nick Roz
  • 103
  • 4
Peter Nunn
  • 452
  • 1
  • 11
  • 25
  • Loosely based on this one-liner, I created a script for providing a human-readable, sorted du(1) output. Please refer to my answer, https://serverfault.com/a/937459/218692. – Tripp Kinetics Oct 26 '18 at 22:10
6

I learned awk from concocting this example yesterday. It took some time, but it was great fun, and I learned how to use awk.

It runs only du once, and it has a output much similar to 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 }'

It shows numbers below 10 with one decimal point.

marlar
  • 461
  • 6
  • 6
6

Here is the simple method I use, very low resource usage and gets you what you need:

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
JacobN
  • 156
  • 2
  • 7
6

Another one:

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

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

Patrick
  • 81
  • 1
  • 2
  • 7
4

If you need to handle spaces you can use the following

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

The additional sed statement will help alleviate issues with folders with names such as Application Support

Chealion
  • 5,733
  • 28
  • 29
2

http://dev.yorhel.nl/ncdu

command: ncdu

Directory navigation, sorting (name and size), graphing, human readable, etc...

  • 1
    Great utility, but not installed by default on any OS I'm aware of. Not necessarily a problem, but one more program to have to look after... – voretaq7 Nov 29 '11 at 23:07
2

Another 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
2

Here is an example

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

Returns:

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

You could also add | head -10 to find the top 10 or any number of sub-folders in the specified directory.

ode2k
  • 174
  • 1
  • 4
1

Voilà:

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

I had been using the solution provided by @ptman, but a recent server change made it no longer viable. Instead, I'm using the following bash 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);
}'
  • The BSD `du -d 1` syntax has been supported by GNU du since coreutils 8.6 was released in 2010 (though its first Red Hat availability was RHEL 7 in 2014), so you no longer need `--maxdepth=1`. I only [found out](https://twitter.com/adamhotep/status/835296778631045120) about this recently myself. – Adam Katz May 03 '17 at 21:47
1

du -s * | sort -nr | cut -f2 | xargs du -sh

1

There are a lot of answers here, many of which are duplicates. I see three trends: piping through a second du call, using complicated shell/awk code, and using other languages.

Here is a POSIX-compliant solution using du and awk that should work on every system.

I've taken a slightly different approach, adding -x to ensure we stay on the same filesystem (I only ever need this operation when I'm short on disk space, so why weed out stuff I've mounted within this FS tree or moved and symlinked back?) and displaying constant units to make for easier visual parsing. In this case, I typically choose not to sort so I can better see the hierarchical structure.

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

(Since this is in consistent units, you can then append | sort -n if you really want sorted results.)

This filters out any directory whose (cumulative) content fails to exceed 512MB and then displays sizes in gigabytes. By default, du uses a 512-byte block size (so awk's condition of 220 blocks is 512MB and its 221 divisor converts the units to GB — we could use du -kx with $1 > 512*1024 and s/1024^2 to be more human-readable). Inside the awk condition, we set s to the size so we can remove it from the line ($0). This retains the delimiter (which is collapsed to a single space), so the final %s represents a space and then the aggregated directory's name. %7s aligns the rounded %.2f GB size (increase to %8s if you have >10TB).

Unlike most of the solutions here, this properly supports directories with spaces in their names (though every solution, including this one, will mishandle directory names containing line breaks).

Adam Katz
  • 951
  • 8
  • 17
0

Here's my solution, a simple bash script that only calls du once, and shows you only directories of size 1 MB or larger:

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

Why not throw another hat into the ring.... it's an old question, but here's an example that is (mostly) pure shell script (fwiw) -- i.e, just bash and no perl/python/awk/etc. So in that sense maybe it offers something new to the discussion (or not). It calculates file size just once, but prints in various units (my preference). (The un-simplified version includes getopts that excludes "GB" if unwanted.)

#!/bin/bash

printf -- ' %9s %9s %9s       %-30s\n' 'K'        'M'        'G'        'Path'
printf -- ' %9s %9s %9s       %-30s\n' '--------' '--------' '--------' '-----------'
du -sk "$@" | 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
michael
  • 384
  • 1
  • 5
0

At least with the usual tools, this will be hard because of the format the human-readable numbers are in (note that sort does a "good job" here as it sorts the numbers - 508, 64, 61, 2, 2 - it just can't sort floating point numbers with an additional multiplier).

I'd try it the other way round - use the output from "du | sort -n -r" and afterwards convert the numbers to human-readable format with some script or program.

schnaader
  • 121
  • 3
0

What you can try is:

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

Hope that helps.

  • that's what xargs does ;-) – cadrian Feb 25 '09 at 14:05
  • hehe, I always forget about xargs. ;) At the end of the day, whatever gets the job done imo. –  Feb 25 '09 at 15:05
  • MacOSX by default (i.e. outside of home-brew) doesn't support a proper `xargs` so this form was necessary. However for files with spaces in them you need to set IFS: `IFS=$'\n'` – HankCa Jan 30 '16 at 11:16
0
du | sort -nr | awk '{ cmd = "du -h -d0 "$2"| cut -f1"; cmd | getline human; close(cmd); print human"\t"$2 }'
0

The following solution is similar to cadrian's original however this will only run 2 du commands as opposed to one du for each directory in the tree.

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

However Cardrian's solution is more robust as the above will not work for very heavily populated trees as it could exceed the limit on the size of the arguments passed to du

Steve Weet
  • 109
  • 3
0

This is the alias I have in my .profile

alias du='sudo du -xh --max-depth=1 | sort -h'

sort -h is what really helps here to the question asked.

Another useful options are du -x to stay on the same filesystem; also sudo helps not to see errors if there are directories that aren't world-readable. Also, I always do du --max-depth=1, then drill down further etc..

Tagar
  • 159
  • 5
0

Sorts in descending order.

du -s ./* | sort -n| cut -f 2-| xargs du -sh {}
dawud
  • 15,096
  • 3
  • 42
  • 61
Peter Nduati
  • 332
  • 1
  • 6
0

Loosely based on the logic in this one-liner, I wrote a script that provides a sorted human-readable du(1) output. Other than requiring the -h flag for human-readability, it requires no other non-POSIX-compatible commands.

It is available at https://github.com/pleappleappleap/sorted-human-du.

0

Yet another du script!

As there is already a lot of answer, I just post my own script there. I use from more than eight years now.

This could by run by

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

where

  • optional flag -b tell to use byte count instead of block count
  • optional path as 1st argument, current directory if default.
  • if no second argument given, minimal size to be printed is 256Mb.

The output could look like:

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

There is the 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:-.}"

You may show script on my own site or download them there.

-2

Instead of raping du and friends, you can use ls alone to do what you want:

ls -1Ssh

That will print all files sorted by size written in human-readable form. The first line it prints is the total, if you want to get rid of it you can simply use

ls -1Ssh | tail -n +2

You can add the -r flag to ls if you want the files in the reversed order (from smallest to largest).

drrlvn
  • 129
  • 3
  • At least here, that doesn't work. `houdini@clanspum:~/ > ls -1Ssh | grep clanspum 4.0K drwxr-xr-x 27 houdini users 4.0K 2010-02-15 12:35 clanspum/ 0 drwxr-xr-x 2 houdini users 77 2010-02-15 13:06 clanspum-s/ houdini@clanspum:~/ > du -sh clanspum/ 602M clanspum/ ` – Bill Weiss Feb 23 '10 at 20:40
  • 4
    ... pretend that was formatted correctly. Point is, it shows a directory as being "4.0K", while `du -sh` shows "602M". The latter is correct. – Bill Weiss Feb 23 '10 at 20:40