Tip: How to sort folders by size with one command line in Linux
I often need to find out what are the biggest folders from the space point of view. Take for example, I need to get the users that are using the most space on the system that gets close to filling up the hard drive. If we consider that the entire user’s data is under /home, I need to have a list of all the subfolders sorted by the size of the subfolders.
This can be achieved in many was on Linux, and for example if you have quota enabled it can be as easy as checking the quota list. But if quota is not enabled on the partition, I am using the following simple command to get the list of subfolders sorted by their size:
du --max-depth=1 /home/ | sort -n -rIf this is really big, as it often is, you might want to direct the output of the command to a file, and check back later in a few minutes when it is finished. ![]()
The result of this will include also the top level folder, and will look like this:
238208 /home/
164340 /home/marius
9324 /home/users
3660 /home/shared
32 /home/admin
...Other ways I use du:
du -H --max-depth=1 /home/userwhere I included “-H” to produce human readable format sizes (like: 1K 101M 2G)
>

3rd July 2006, 12:54
[...] Tip: How to sort folders by size with one command line in Linux | MDLog:/sysadmin [...]
18th July 2006, 15:27
I usually use something similar, but smaller to type:
du -sc /* | sort -nr
It is important to have the * because of the -s flag.
But remember that with this construction you miss the hidden files (files starting with a dot), because the shell-expansion of * doesn’t catch them.
20th July 2006, 22:13
I use this so often I stuck it in a shell script a couple years ago (could be improved):
—–
dutop.sh
—–
#!/bin/sh
dudir=”.”
topn=”10″
if [ "$1" ]; then
topn=”$1″
fi
if [ "$2" ]; then
dudir=”$2″
fi
du –max-depth 1 “$dudir” | sort -rn | head -”$topn”
7th December 2006, 03:39
du -sh * |grep G or du -sh * |grep M gives fast result
Jason.
http://linux-tweaks.blogspot.com
13th May 2007, 12:54
I’d been wondering how to get a sorted, human readable listing with du, and finally figured out a fairly short way to do it:
du -s /* | sort -n | cut -f 2- | while read a; do du -sh “$a”; done
This prints a sorted list in human-readable format, only problem with it is that the du is essentially done twice. That is not a major problem however as caching makes the second run really fast.
15th October 2007, 19:34
this is a one-liner that will show size for all folders inside current folder, including hidden ones, sorted and “human-readable”. For being a one-liner it’s kind of long, so I put it in a script file,
——-
duall
——
#!/bin/bash
ls -laQ | grep -r ‘^d’ | grep -v ‘\ \”\.\”$’ | grep -v ‘\ \”\.\.\”$’ | sed -r ‘s/.*\ \”(.*)\”$/\1/’ | while read a; do du -s “$a”; done | sort -n | sed -r ‘s/^([0-9]{1,4})\t(.*)/ \1\t\2/’ | sed -r ‘s/^([\ 0-9]{4,5})\t(.*)/ \1\t\2/’ | sed -r ‘s/^([\ 0-9]{6})\t(.*)/ \1\t\2/’ | sed -r ‘s/^([\ 0-9])([\ 0-9]{3})([\ 0-9]{3})\t(.*)/\1 \2 \3\t\4/’
2nd November 2007, 01:45
Bang! This one liner bombs “syntax error near unexpected token”
I think I’ll patch sort to understand ’10.2G’ etc.
2nd November 2007, 01:57
All the single quote and double quote characters are turned into some wierd unicode nastiness. Changing them to standard characters makes the script work. The output format is pretty nasty but never mind – I just found a hidden 8GB directory that’s not needed! Thanks!
16th November 2007, 17:52
du -s */ .[^.]*/ | sort -nr
is a good way to get the hidden directories as well. If you like the outrageously nice output format Kunchok called “pretty nasty,” then here’s an optimized version of the above “one-liner”:
#!/bin/bash
if [ "a$1" != "a" ]; then
cd $1
fi
du -s */ .[^.]*/ | sort -n | while read a; do echo ” $a”; done | sed -r ‘s/^ *([ 0-9]{3})([ 0-9]{3})([ 0-9]{3}) *(.*)\/$/\1 \2 \3 \4/’
11th February 2008, 22:33
When running the script above I received “Syntax error: “(” unexpected”.
Here is an edit that works for me with a couple additions.
#!/bin/bash
if [ “a$1″ != “a†]; then
cd $1
fi
du –si */ .[^.]*/ | sort -n | while read a; do echo †$aâ€; done | sed -r ‘s/^\ *([\ 0-9]{3})([\ 0-9]{3})([ 0-9]{3})\ *(.*)\/$/\1 \2 \3 \4/’ | egrep -v “k\ “
4th December 2008, 18:49
A good and short one liner using xargs
du -s ./* | sort -n| cut -f 2-|xargs -i du -sh {}
This will sort the folders according to size and display them in human readable format… to reverse the list
sue sort -nr option…
7th January 2009, 17:24
Same as you, with a diff look of sort
$ du –max-depth=1 . | sort +0nr
http://unstableme.blogspot.com/
31st March 2009, 13:06
[...] http://www.ducea.com/2006/05/14/tip-how-to-sort-folders-by-size-with-one-command-line-in-linux/ [...]
31st March 2009, 13:20
[...] * http://www.yaroman.com/2007/08/14/how-to-sort-files-and-folders-by-size/ * http://www.ducea.com/2006/05/14/tip-how-to-sort-folders-by-size-with-one-command-line-in-linux/ * http://www.ubuntugeek.com/how-to-sort-files-and-folders-by-size.html * [...]
6th August 2009, 09:09
using sort -nr is not that clean since it sort by numbers not by the size of the file so in my output it does this:
972K ./tools <– Sort looks at the 972 and put is on top of all the others…
412M ./changes
212M ./modules
68K ./images
36K ./changelog.txt
20K ./GNU_GPL
12K ./slaxsave.zip
6th August 2009, 13:03
That’s because you use du with the -h option together with sort.
2nd September 2009, 16:54
I was looking for this command because my usr partition says it uses 10 gigs yet my du output shows only 4 being used. Anyway to check for sure the full size a of a partition and what folders in it are the largest. Even better what folder with no other folders in it is the biggest.
BTW this one takes a long time and runs up the CPU pretty high: du -s /* | sort -n | cut -f 2- | while read a; do du -sh “$a”; done
I’m still waiting for it.
Normally I use: du -H –max-depth=1 /usr/local/ | sort -n -r
2nd September 2009, 17:02
du -s /* | sort -n | cut -f 2- | while read a; do du -sh “$a”; done
Just gave a bunch of cannot read file errors, I would skip it.
6th October 2009, 09:14
du –all –max-depth=1 $@ | sort -n | awk ‘{if ($1>1048576) {print int($1/1048576)”G”,$2}else if ($1>1024) {print int($1/1024)”M”,$2} else {print $1″K”,$2}}’
21st October 2009, 23:48
Ok, all of these work. But what would be a way to do this really fast. I’ve a 3TB area of user homes on a NAS and I need to do this weekly and deliver a report.
14th November 2009, 17:17
To have it done fast, just use quota. Or pick your favourite version above, just stay away from the ones with more than one call to du.
3rd December 2009, 22:24
Here is only one run of du and no temp files. It is about as efficient as you can get.
du -shx | perl -e ‘%byte_order = ( G => 0, M => 1, K => 2 ); print map { $_->[0] } sort { $byte_order{$a->[1]} $byte_order{$b->[1]} || $b->[2] $a->[2] } map { [ $_, /([MGK])/, /(\d+)/ ] } ‘
3rd December 2009, 22:29
du -shx | perl -e ‘%byte_order = ( G => 0, M => 1, K => 2 ); print map { $_->[0] } sort { $byte_order{$a->[1]} \ $byte_order{$b->[1]} || $b->[2] \ $a->[2] } map { [ $_, /([MGK])/, /(\d+)/ ] } \’
command needed some commenting to get past the \s probably html interpretation.
3rd December 2009, 22:31
Grrr.. using code flag..
du -shx | | perl -e '%byte_order = ( G => 0, M => 1, K => 2 ); print map { $_->[0] } sort { $byte_order{$a->[1]} $byte_order{$b->[1]} || $b->[2] $a->[2] } map { [ $_, /([MGK])/, /(\d+)/ ] } '
3rd December 2009, 22:38
du -shx | perl -e ‘%byte_order = ( G => 0, M => 1, K => 2 ); print map { $_->[0] } sort { $byte_order{$a->[1]} <=> $byte_order{$b->[1]} || $b->[2] [2] } map { [ $_, /([MGK])/, /(\d+)/ ] } <>’
breaking out the html manaul… <$gt..
3rd December 2009, 22:39
nope, good luck
7th January 2010, 00:30
The script works good with perl, but I’m curious if Terabyte can be added to it too. I don’t know much perl so it would be great if T can be added in the mix also.
Thanks
7th January 2010, 18:57
Sure, just need to bump the numbering in the byte_order hash over and add T to the regex match.
du -shx | perl -e ‘%byte_order = ( T => 0, G => 1, M => 2, K => 3 ); print map { $_->[0] } sort { $byte_order{$a->[1]} <=> $byte_order{$b->[1]} || $b->[2] <=> $a->[2] } map { [ $_, /([MTGK])/, /(\d+)/ ] } <>’
Though it is probably better still to change the regex from /([MTGK])/ to /^\d+(\S)/ Since that will match more generically and not at all on sub K output lines, as it should.
Or even better still (only runs the regex once for each line):
du -shx | perl -e ‘%byte_order = ( T => 0, G => 1, M => 2, K => 3 ); print map { $_->[0] } sort { $byte_order{$a->[1]} <=> $byte_order{$b->[1]} || $b->[2] <=> $a->[2] } map { /^(\d+)(\S)/; [ $_, $2, $1 ] } <>’
7th January 2010, 21:41
Actually sub K file sizes remain a bug. A match for null case is needed. Also decimal values break the new regex. That needs to be accounted for in the pattern. This one should be final:
du -shx * | perl -e ‘%byte_order = ( T => 0, G => 1, M => 2, K => 3, “” => 4 ); print map { $_->[0] } sort { $byte_order{$a->[1]} <=> $byte_order{$b->[1]} || $b->[2] <=> $a->[2] } map { /^(\d+(?:\.\d+){0,1})(\S)/; [ $_, $2, $1 ] } <>’
27th January 2010, 20:05
One another :
du –si */ .[^.]*/ | sort -n | while read a; do echo †$aâ€; done | sed -r ’s/^\ *([\ 0-9]{3})([\ 0-9]{3})([ 0-9]{3})\ *(.*)\/$/\1 \2 \3 \4/’ | egrep -v “k\ “ | grep du -shx * | perl -e ‘%byte_order = ( T => 0, G => 1, M => 2, K => 3, “” => 4 ); print map { $_->[0] } sort { $byte_order{$a->[1]} <=> $byte_order{$b->[1]} || $b->[2] <=> $a->[2] } map { /^(\d+(?:\.\d+){0,1})(\S)/; [ $_, $2, $1 ] } <>’ | sed s -laQ | grep -r ‘^d’ | grep -v ‘\ \”\.\”$’ | grep -v ‘\ \”\.\.\”$’ | sed -r ’s/.*\ \”(.*)\”$/\1/’ | while read a; do du -s “$a”; done | sort -n | sed -r ’s/^([0-9]{1,4})\t(.*)/ \1\t\2/’ | sed -r ’s/^([\ 0-9]{4,5})\t(.*)/ \1\t\2/’ | sed -r ’s/^([\ 0-9]{6})\t(.*)/ \1\t\2/’ | sed -r ’s/^([\ 0-9])([\ 0-9]{3})([\ 0-9]{3})\t(.*)/\1 \2 \3\t\4/’ –all –max-depth=1 $@ | sort -n | awk ‘{if ($1>1048576) {print int($1/1048576)”G”,$2}else if ($1>1024) {print int($1/1024)”M”,$2} else {print $1?K”,$2}}’
14th April 2010, 23:36
Fab, that’s a joke right? You gotta be kidding.
3rd June 2010, 21:06
Hi, just wanted to include my version of what I read here – it uses sort on raw bytes, and then uses bc (could be wcalc too) to calculate KB for display:
du –max-depth=1 /usr | sort -n -r | while read line ; do arr=($line) ; echo $(echo “scale=4; ${arr[0]}/1024″ | bc) KB – ${arr[1]} ;
4th June 2010, 17:45
Sorry, seems du needs -b to specify sizes in bytes for the above to be correct, so here is another attempt – this time also in pre tags
du -b -x –max-depth=1 / 2>/dev/null | sort -n -r | while read line ; do arr=($line) ; echo $(echo “scale=4; ${arr[0]}/1024″ | bc) KB – ${arr[1]} ; done
4th June 2010, 17:49
Just a rewrite with code tag – pre seems to get sanitized
du -b -x –max-depth=1 / 2>/dev/null | sort -n -r | while read line ; do arr=($line) ; echo $(echo "scale=4; ${arr[0]}/1024" | bc) KB – ${arr[1]} ; done
7th February 2011, 01:22
du -H –max-depth=1 /home/user
simple n best command to sort size wise. thks for the help
18th February 2011, 04:27
du -h --summarize * | sort -hI do not know when coreutils added –summarize, but it displays the total size for the target. sort also has a -h flag to sort “human readable numbers” e.g. 1.4G.
I know this is quite an old post but I think people should learn about the new flags.
16th June 2011, 08:05
the summarize has been around forever and is the same as the -s in some of the earlier comments.
The human readable sort I don’t know when it was added but it made my life easier for a while now.
Obligatory line I use: du -hs * | sort -hr | head
20th September 2011, 18:36
du -sh /home/user
10th November 2011, 01:26
To catch the hidden files?
ls -A | while read x; do du -s “$x”; done | sort -nr
23rd January 2012, 11:24
[...] From: http://www.ducea.com/2006/05/14/tip-how-to-sort-folders-by-size-with-one-command-line-in-linux/ [...]