I'm looking to list the entire contents of a directory, including the contents of subfolders but sorted by filesize.
Thus far I've managed to get as far as listing and sorting whilst still being recursive with ls -lhSR
(the h
is nice to have but definitely not essential for me, as long as I can get file sizes).
I am likely overlooking something obvious, or asking the impossible, but any advice here would be greatly appreciated.
You can use find:
Optional: To convert byte values to human-readable format, add this:
Explanation:
Since you didn't specify a particular shell, here's an alternative using zsh's glob qualifiers with
for the recursion. Then for example:
recursively list plain files:
recursively list plain files, ordered by increasing Length (i.e. size):
recursively list plain files, Ordered by decreasing size:
recursively list plain files, ordered by decreasing size, and select the top 3 results:
If you want the file sizes as well, then you could use
With the
globstar
shell option set you can use shell globbing:If you try that with too many files, you‘ll get an “Argument list too long” error. To work around that, you can use
printf
andxargs
:I just realized this prints the directories (with a size of 4096 bytes) as well – if you don’t want that, use this instead:
Example run
If you don't have zsh, you can still use
du
+sort
:Human-readable sizes, including cumulative sizes of directories:
Only files (using
find
):In both cases, I have opted to use null-terminated lines (
-0
,-z
,-print0
options), to be safe against all valid filenames.For quick interactive use on directory trees that aren't too huge,
shopt -s globstar
is really nice. A glob can't filter out directories based on type, but if you use it withls -d
thenls
will just print the directory name, instead of the contents.Assuming your
ll
alias includes-lh
:will give you output like this (from my code-golf directory), but with colour highlighting (so it's easier to see the directories). Note that sorting by filesize happened across subdirectories.
You could filter out the directories by piping through
grep -v '^d'
You can sometimes use a glob that matches only files and not directories, if your filenames have a pattern. e.g.
ll -rSd **/*.jpg
, or even**/*.*
works if none of your directory names have.
in them, and all the files you want do.(For people with a DOS background: there's nothing magical about
*.*
on Unix. It just matches any directory entry that contains a literal dot. But other than executables and sometimes text files, it's common to give extensions to filenames.)@dessert points out you would need
shopt -s dotglob
for it to match all files.With GNU
find
If there aren't too many files to fit on one
ls
command line,find -exec ls {} +
will put them all on on command line wherels
can sort them.Using
-not -type d
instead of-type f
avoids ignoring symlinks, named pipes, sockets, device files, and whatever else you have kicking around in your directories.With
du
:Now directory names are sorted into the list with to sum total of all their contents, but individual files are still included.
sort -h
, aka--human-numeric-sort
, sorts numbers with size suffixes likedu -h
prints. It's perfect for use withdu
.I often use
du -sch * | sort -h
, or*/
to get only directories.du -sch **/* | sort -h
would give you the above output, if you forget thatdu
has a-a
option.(I only took the time to look it up because I'm posting an answer. For interactive use, I probably would have just used
du -sch **/*
.