#!/bin/sh
#\- sort by size a "du" listing; filter only
#usage: %dusort [-t]
#typically: du | dusort [-t]
#sort a "du" listing by directory size and format
#option: -t => output format =  dir(size)    default => size	dir
#
#BUG: if two or more directories with same path have same size, then
#their subdirectories will be sorted together and printed as a block
#after the directories are printed as a block.
#
#by conor rafferty, stanford
#(X-Archive: comp.sources.misc/8709/10)
#slightly modified by ja rupley, tucson, arizona

FILES=
TFORM=0
while test $# -ge 1; do
    case $1 in
    -t)	TFORM=1; ;;
    *)  FILES="$FILES $1"; ;;
    esac
    shift
done


#build complex keys so that subdirectories move with parent
awk '{ size[ $2] = $1 }
END {
	for (i in size) {
		printf "%s ", i;
		oj = 1; l = length(i);
		#build up an aggregate key from all its parents
		for (j = 1; j <= l; ) {
			for (; j <= l; j++) if (substr(i,j,1) == "/") break;
			name = substr(i, oj, j-oj);
			j++;
			printf "%d ", size[name];
		}
		#print itself once more to compare ahead of its children
		printf "%d\n", size[i];
	}
}'  $FILES |

#sort numerically
sort -r -n +1 -2 +2 -3 +3 -4 +4 -5 +5 -6 +6 -7 +7 -8 +8 -9|

#just print the path and its size. In two popular flavors.
awk '{if('$TFORM') printf "%s(%d)\n", $1, $NF; else
		   printf "%8d\t%s\n", $NF, $1}' |

#indent directories
# This awk could be combined with the previous one
# but it really performs a separate function.
# Cut it off and put it in a separate file called 'ind' if you like it.
#
# ind: indent output from du or find
#
awk '
BEGIN {blank="                                                          "}
{
    for (s=length; s > 0 && substr($0, s, 1) > " " ; s--)
	;
    for (e=length; substr($0, e, 1) != "/" && e > s+1; e--)
	;
    print  substr($0, 1, s) substr(blank, 1, e-s-1) substr($0, e);
}
'
