//View Tip #275
» Counts files in the current directory and subdirectory
» Randomize lines in a file
» Get your IP in one line
» MAC address conversion
hpt
Similar Tips
» Directories and its size» Counts files in the current directory and subdirectory
» Randomize lines in a file
» Get your IP in one line
» MAC address conversion
Latest tips by RSS
Click here to subscribe
Follow Shell-Fu on Twitter
Click here to follow
Follow Shell-Fu on identi.ca
Click here to follow
This piece of code lists the size of every file and subdirectory of the current directory, much like du -sch ./* except the output is sorted by size, with larger files and directories at the end of the list. Useful to find where all that space goes.
du -sk ./* | sort -n | awk 'BEGIN{ pref[1]="K"; pref[2]="M"; pref[3]="G";} { total = total + $1; x = $1; y = 1; while( x > 1024 ) { x = (x + 1023)/1024; y++; } printf("%g%s\t%s\n",int(x*10)/10,pref[y],$2); } END { y = 1; while( total > 1024 ) { total = (total + 1023)/1024; y++; } printf("Total: %g%s\n",int(total*10)/10,pref[y]); }'
Comments
Add your comment
Comments are currently disabled
#1
why "x = (x + 1023)/1024", it should be "x = x / 1024" I think ...
Posted 2008-09-18 10:42:38
du -ksh ./* | sort -n gets close, but doesn't sort files of different size classes correctly, for example I get:
1.2M ./Folder1
4.3G ./Folder2
301M ./Folder3
640K ./Folder4
680K ./Folder5
I made an attempt that doesn't use any math, but as a result you don't get the total size for the current directory, which I miss. (You could of course just run another du -sh, but that would take a lot longer than the posted script. Anyway, here's my version for the fun of it, but I'll still stick with the OP. Thanks, I love it!
alias dstat="du -sh ./* | sed -e 's/^\([0-9\.]*\)K/A \1/g' -e 's/^\([0-9\.]*\)M/B \1/g' -e 's/^\([0-9\.]*\)G/C \1/g' -e 's/^\([0-9\.]*\)T/D \1/g' | sort -k1.1,1.2d -k2n | sed -e 's/^A \([0-9\.]*\)/\1K/g' -e 's/^B \([0-9\.]*\)/\1M/g' -e 's/^C \([0-9\.]*\)/\1G/g' -e 's/^D \([0-9\.]*\)/\1T/g'"
1.2M ./Folder1
4.3G ./Folder2
301M ./Folder3
640K ./Folder4
680K ./Folder5
I made an attempt that doesn't use any math, but as a result you don't get the total size for the current directory, which I miss. (You could of course just run another du -sh, but that would take a lot longer than the posted script. Anyway, here's my version for the fun of it, but I'll still stick with the OP. Thanks, I love it!
alias dstat="du -sh ./* | sed -e 's/^\([0-9\.]*\)K/A \1/g' -e 's/^\([0-9\.]*\)M/B \1/g' -e 's/^\([0-9\.]*\)G/C \1/g' -e 's/^\([0-9\.]*\)T/D \1/g' | sort -k1.1,1.2d -k2n | sed -e 's/^A \([0-9\.]*\)/\1K/g' -e 's/^B \([0-9\.]*\)/\1M/g' -e 's/^C \([0-9\.]*\)/\1G/g' -e 's/^D \([0-9\.]*\)/\1T/g'"
Posted 2009-02-27 06:08:38
The '$2' in awk will not print the entire filenames. Also, the math there is not correct - doesnot match with individual du -sh values!
I like spud's solution which I modified to:
find . -maxdepth 1 -type d -print0 | xargs -0 du -sh | sed 's/^\([0-9\.]*\)\([KMGT]\)/\2 \1/;s/^G/N/' | sort -k1.1,1.2d -k2n | sed 's/^N/G/;s/^\([KMGT]\) \([0-9\.]*\) *\(.*\)/\2 \1 \3/' | awk '{printf("%5.1f %c %s\n",$1,$2,gensub(/^[[:digit:]\. ]* [KMGT][ \t]*/,"",""))}'
You may remove '-type d' to get all files and dirs (but not recursing). Also, in spud's solution, no need to change K, M, and T; 'G' is the only odd ball!
I like spud's solution which I modified to:
find . -maxdepth 1 -type d -print0 | xargs -0 du -sh | sed 's/^\([0-9\.]*\)\([KMGT]\)/\2 \1/;s/^G/N/' | sort -k1.1,1.2d -k2n | sed 's/^N/G/;s/^\([KMGT]\) \([0-9\.]*\) *\(.*\)/\2 \1 \3/' | awk '{printf("%5.1f %c %s\n",$1,$2,gensub(/^[[:digit:]\. ]* [KMGT][ \t]*/,"",""))}'
You may remove '-type d' to get all files and dirs (but not recursing). Also, in spud's solution, no need to change K, M, and T; 'G' is the only odd ball!
Posted 2009-04-29 22:10:22
The above complex solutions are ridiculous.
When using du you can specify more than one pattern match, so the simplest solution is
du -ks ./* ./.* | sort -n
which will show everything in kilobytes.
(use -ms for megabytes)
When using du you can specify more than one pattern match, so the simplest solution is
du -ks ./* ./.* | sort -n
which will show everything in kilobytes.
(use -ms for megabytes)
Posted 2009-05-24 18:50:27
Damn! I wrote this myself
$ type dusa
dusa is a function
dusa ()
{
du -a --max-depth=1 | sort -n | awk '{
sub("./","",$2);
size=$1;
$1="";
unit="K";
if (size >= 1024)
{
size = size /1024;
unit="M";
}
if (size >= 1024)
{
size = size /1024;
unit="G";
}
printf "%6.1f%s %s\n", size, unit, $0;
}'
}
A bit later I heard about the program ncdu (http://dev.yorhel.nl/ncdu). It's really cool.
$ type dusa
dusa is a function
dusa ()
{
du -a --max-depth=1 | sort -n | awk '{
sub("./","",$2);
size=$1;
$1="";
unit="K";
if (size >= 1024)
{
size = size /1024;
unit="M";
}
if (size >= 1024)
{
size = size /1024;
unit="G";
}
printf "%6.1f%s %s\n", size, unit, $0;
}'
}
A bit later I heard about the program ncdu (http://dev.yorhel.nl/ncdu). It's really cool.
Posted 2009-06-07 10:46:34
This only works with GNU Coreutils:
du -k --max-depth=1 | sort -rgb
The "--max-depth" flag saves a lot of unecessary scripting fluff compared to non-GNU versions.
Likewise, the "sort -rgb" is GNU-only. "sort -rn" is the equivalent elsewhere.
du -k --max-depth=1 | sort -rgb
The "--max-depth" flag saves a lot of unecessary scripting fluff compared to non-GNU versions.
Likewise, the "sort -rgb" is GNU-only. "sort -rn" is the equivalent elsewhere.
Posted 2009-06-14 07:01:09

