Sorting files according to size recursively

You can also do this with just du. Just to be on the safe side I'm using this version of du:

$ du --version
du (GNU coreutils) 8.5

The approach:

$ du -ah ..DIR.. | grep -v "/$" | sort -rh

Breakdown of approach

The command du -ah DIR will produce a list of all the files and directories in a given directory DIR. The -h will produce human readable sizes which I prefer. If you don't want them then drop that switch. I'm using the head -6 just to limit the amount of output!

$ du -ah ~/Downloads/ | head -6
4.4M    /home/saml/Downloads/kodak_W820_wireless_frame/W820_W1020_WirelessFrames_exUG_GLB_en.pdf
624K    /home/saml/Downloads/kodak_W820_wireless_frame/easyshare_w820.pdf
4.9M    /home/saml/Downloads/kodak_W820_wireless_frame/W820_W1020WirelessFrameExUG_GLB_en.pdf
9.8M    /home/saml/Downloads/kodak_W820_wireless_frame
8.0K    /home/saml/Downloads/bugs.xls
604K    /home/saml/Downloads/netgear_gs724t/GS7xxT_HIG_5Jan10.pdf

Easy enough to sort it smallest to biggest:

$ du -ah ~/Downloads/ | sort -h | head -6
0   /home/saml/Downloads/apps_archive/monitoring/nagios/nagios-check_sip-1.3/usr/lib64/nagios/plugins/check_ldaps
0   /home/saml/Downloads/data/elasticsearch/nodes/0/indices/logstash-2013.04.06/0/index/write.lock
0   /home/saml/Downloads/data/elasticsearch/nodes/0/indices/logstash-2013.04.06/0/translog/translog-1365292480753
0   /home/saml/Downloads/data/elasticsearch/nodes/0/indices/logstash-2013.04.06/1/index/write.lock
0   /home/saml/Downloads/data/elasticsearch/nodes/0/indices/logstash-2013.04.06/1/translog/translog-1365292480946
0   /home/saml/Downloads/data/elasticsearch/nodes/0/indices/logstash-2013.04.06/2/index/write.lock

Reverse it, biggest to smallest:

$ du -ah ~/Downloads/ | sort -rh | head -6
10G /home/saml/Downloads/
3.8G    /home/saml/Downloads/audible/audio_books
3.8G    /home/saml/Downloads/audible
2.3G    /home/saml/Downloads/apps_archive
1.5G    /home/saml/Downloads/digital_blasphemy/db1440ppng.zip
1.5G    /home/saml/Downloads/digital_blasphemy

Don't show me the directory, just the files:

$ du -ah ~/Downloads/ | grep -v "/$" | sort -rh | head -6 
3.8G    /home/saml/Downloads/audible/audio_books
3.8G    /home/saml/Downloads/audible
2.3G    /home/saml/Downloads/apps_archive
1.5G    /home/saml/Downloads/digital_blasphemy/db1440ppng.zip
1.5G    /home/saml/Downloads/digital_blasphemy
835M    /home/saml/Downloads/apps_archive/cad_cam_cae/salome/Salome-V6_5_0-LGPL-x86_64.run

If you want to exclude all directories from the output, you can use a trick with the presence of a dot character. This assumes that your directory names do not contain dots, and that the files you are looking for do. Then you can filter out the directories with grep -v '\s/[^.]*$':

$ du -ah ~/Downloads/ | grep -v '\s/[^.]*$' | sort -rh | head -2
1.5G    /home/saml/Downloads/digital_blasphemy/db1440ppng.zip
835M    /home/saml/Downloads/apps_archive/cad_cam_cae/salome/Salome-V6_5_0-LGPL-x86_64.run

If you just want the list of smallest to biggest, but the top 6 offending files you can reverse the sort switch, drop (-r), and use tail -6 instead of the head -6.

$ du -ah ~/Downloads/ | grep -v "/$" | sort -h | tail -6
835M    /home/saml/Downloads/apps_archive/cad_cam_cae/salome/Salome-V6_5_0-LGPL-x86_64.run
1.5G    /home/saml/Downloads/digital_blasphemy
1.5G    /home/saml/Downloads/digital_blasphemy/db1440ppng.zip
2.3G    /home/saml/Downloads/apps_archive
3.8G    /home/saml/Downloads/audible
3.8G    /home/saml/Downloads/audible/audio_books

If you want to find all files in the current directory and its sub directories and list them according to their size (without considering their path), and assuming none of the file names contain newline characters, with GNU find, you can do this:

find . -type f -printf "%s\t%p\n" | sort -n

From man find on a GNU system:

   -printf format
          True; print format  on  the  standard  output,
          interpreting  `\'  escapes and `%' directives.
          Field widths and precisions can  be  specified
          as  with the `printf' C function.  Please note
          that many of the  fields  are  printed  as  %s
          rather  than  %d, and this may mean that flags
          don't work as you  might  expect.   This  also
          means  that  the `-' flag does work (it forces
          fields to be  left-aligned).   Unlike  -print,
          -printf  does  not add a newline at the end of
          the string.  The escapes and directives are:

          %p     File's name.
          %s     File's size in bytes.

From man sort:

   -n, --numeric-sort
          compare according to string numerical value

Try the following command:

ls -1Rhs | sed -e "s/^ *//" | grep "^[0-9]" | sort -hr | head -n20

It'll list top-20 biggest files in the current directory recursively.

Note: The option -h for sort is not available on OSX/BSD, so you've to install sort from coreutils (e.g. via brew) and apply the local bin path to PATH, e.g.

export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH" # Add a "gnubin" for coreutils.

Alternatively use:

ls -1Rs | sed -e "s/^ *//" | grep "^[0-9]" | sort -nr | head -n20

For the biggest directories use du, e.g.:

du -ah . | sort -rh | head -20

or:

du -a . | sort -rn | head -20