Sorting files according to size recursively
Solution 1
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
Solution 2
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
Solution 3
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
Solution 4
This will find all files recursively, and sort them by size. It prints out all file sizes in kb, and rounds down so you may see 0 KB files, but it was close enough for my uses, and works on OSX.
find . -type f -print0 | xargs -0 ls -la | awk '{print int($5/1000) " KB\t" $9}' | sort -n -r -k1
Solution 5
Simple solution for Mac/Linux which skips directories:
find . -type f -exec du -h {} \; | sort -h
Related videos on Youtube
Bob Ramsey
Updated on September 18, 2022Comments
-
Bob Ramsey almost 2 years
I need to find the largest files in a folder.
How do I scan a folder recursively and sort the contents by size?I have tried using
ls -R -S
, but this lists the directories as well.
I also tried usingfind
.-
Admin almost 11 yearsDo you want to list the files in each subdirectory separately or do you want to find all files in all subdirs and list them by size irrespective of which subdir they are in? Also, what do you mean by "directory" and "folder"? You seem to be using them to describe different things.
-
Admin almost 11 yearsAre you saying that you just want to list the files in a given directory as well as the files in its sub-directories without showing just the sub-directories? Please try and clean up you question, it's not very clear.
-
Admin almost 7 years
-
-
Jan Warchoł over 9 yearsThe
grep -v "/$"
part doesn't seem to be doing what you expected, as the directories don't have a slash appended. Does anyone know how to exclude directories from results? -
slm over 9 years@JanekWarchol - what version of coreutils are you using?
-
Jan Warchoł over 9 yearsI'm on 8.13. But anyway, the output in your answer doesn't have trailing
/
s either - for example/home/saml/Downloads/audible
seems to be a directory, but it doesn't have a slash. Only/home/saml/Downloads/
has a slash, but that's probably because you wrote it with a slash when specifying the argument for initialdu
. -
slm over 9 years@JanekWarchol - Look at the 5th text box. The grep is just to filter the
~/Downloads/
bit out. As you've stated, it's just to filter out the argument of~/Downloads
whendu
processes it. I changed the word directories to directory since I think that's ultimately what was causing the confusion. Thanks for the feedback! -
slm over 9 years@JanekWarchol - incidentally to omit the directories you'll have to change tactics and use
find
to generate a list of files only and then havedu
tally them up. -
Artem almost 8 yearsworked on Ubuntu 14.04 too!
-
ekerner almost 7 yearsThis finds dirs also
-
Roman Gaufman over 6 yearsThis doesn't list just files, but also lists directories :(
-
Roman Gaufman over 6 yearsDoesn't work on Mac unfortunately, shows: find: -printf: unknown primary or operator
-
Roman Gaufman over 6 yearsThis lists directories, not just files :(
-
Roman Gaufman over 6 yearsPerfect, this is the first solution that works on Mac and doesn't show directories :) - thank you!
-
terdon over 6 years@RomanGaufman yes, that's why the answer specifies GNU find. If you install the GNU tools on your Mac, it will work there too.
-
Brad Parks over 6 years@RomanGaufman - thanks for the feedback! from my tests,
find . -type f
finds files... it works recursively, you're right, but it lists all the files it finds, not the directories themselves -
schily about 6 yearsXargs has been used in the 1980s. It is a bad idea since 1989 when execplus has been introduced by David Korn.
-
Matrix about 5 yearshow filter to show only file with number of lines >= X ? (X = 0 for exemple)
-
Ryan Shirley over 4 yearsdu --version in not an option for me, however the approach does work
-
mircealungu over 4 yearsthere's no need for the
-s
insort
. or? -
flochtililoch about 4 yearsbuilding on that solution, and the solution offered on this post: unix.stackexchange.com/questions/22432/…, I was able to yield a result with files only with the following command:
find . -type f -exec du -ah {} + | grep -v "/$" | sort -rh
-
Student about 4 years@flochtililoch Super answer! It works for me :)
-
nyanpasu64 almost 4 yearsUse
du --apparent-size
to view the length of the file in bytes (not the size taken on disk). -
odony almost 4 years@JanWarchoł I could not find any way for
du
to provide a different output for directory (-S
changes their size, not the output format). So I resorted to a workaround that assumes that your directory names do not have any dots in them, and that the files you care about do. In that case you can replace the non-workinggrep -v '/$'
bygrep -v '\s/[^.]*$'
. And you have to make sure you specify DIR as an absolute path, so there is no dot in there. -
Kamil Dziedzic almost 3 yearsHow about listing only directories, I'm not interested in files.
-
Erikw about 2 yearsGreat command but one problem: It does not handle filenames well with spaces. Only the part up until the first space will be printed as of
$9
. I tried to improve on this by printing ranges $9-end. I ended up with:find "$path" -type f -print0 | xargs -0 ls -la | awk '{for (i=5; i<NF; i++) { if (i == 5) { printf int($i/1024) " KiB\t" } else if (i >= 9 ) { printf $i " " } }; if (NF >= 5) print $NF; }' | sort -n -r -k1
. It seems to work, but feedback is much welcome to make this a bit more concise -
Admin about 2 yearsYou can also use "%P" (uppercase) which is: "File's name with the name of the starting-point under which it was found removed". In this case it would remove the "./" at the beginning of each path.