How to sort human readable size
Try sort -h k2
-h, --human-numeric-sort compare human readable numbers (e.g., 2K 1G)
It is part of gnu sort, BSD sort, and others.
ls
has this functionality built in, use the -S
option and sort in reverse order: ls -lShr
-r, --reverse
reverse order while sorting
-S sort by file size, largest first
Since no specific shell was mentioned, here's how to do the whole thing in the zsh
shell:
ls -lhf **/*(.Lk-1024oL)
The **
glob pattern matches like *
but across /
in pathnames, i.e. like a recursive search would do.
The ls
command would enable human readable sizes with -h
, and long list output format with -l
. The -f
option disables sorting, so ls
would just list the files in the order they are given.
This order is arranged by the **/*(.Lk-1024oL)
filename globbing pattern so that the smaller files are listed first. The **/*
bit matches every file and directory in this directory and below, but the (...)
modifies the glob's behaviour (it's a "glob qualifier").
It's the oL
at the end that orders (o
) the names by file size (L
, "length").
The .
at the start makes the glob only match regular files (no directories).
The Lk-1024
bit selects files whose size is less than 1024 KB ("length in KB less than 1024").
If zsh
is not your primary interactive shell, then you could use
zsh -c 'ls -lf **/*(.Lk-1024oL)'
Use setopt GLOB_DOTS
(or zsh -o GLOB_DOTS -c ...
)
to also match hidden names. ... or just add D
to the glob qualifier string.
Expanding on the above, assuming that you'd want a 2-column output with pathnames and human readable sizes, and also assuming that you have numfmt
from GNU coreutils,
zmodload -F zsh/stat b:zstat
for pathname in **/*(.Lk-1024oL); do
printf '%s\t%s\n' "$pathname" "$(zstat +size "$pathname" | numfmt --to=iec)"
done
or, quicker,
paste <( printf '%s\n' **/*(.Lk-1024oL) ) \
<( zstat -N +size **/*(.Lk-1024oL) | numfmt --to=iec )