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 )

Tags:

Find

Ls

Sort