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