SnippetBash

Rank files by size, biggest first

Ranks every file under a directory by actual size, human-readable and biggest-first, using only find, du, sort and head.

Last updated

Snippetbash
find . -type f -exec du -h {} + | sort -rh | head -n 10

How it works

The + at the end of -exec batches many files into a single du invocation instead of forking one process per file (the \; form), which on a large tree is the difference between instant and unbearable — the output is byte-identical either way. -type f already guarantees du only ever receives files, so no rolled-up directory total can creep into the list.

sort -rh understands human-readable size suffixes directly (1K, 1M, 1G) and orders them by actual magnitude rather than alphabetically — without -h, plain sort -r would put "9K" ahead of "1G" because it's comparing the leading digit as text. head -n 10 then trims the sorted output to the top 10; change that number for more or fewer results.

Edge cases to know

  • →du reports disk space ALLOCATED, not the apparent file size — a 5,000-byte file usually shows as 8.0K because it occupies two 4K blocks. Add --apparent-size on GNU du if you want true byte counts.
  • →This ranks by size; to find files merely over a threshold, find . -type f -size +100M is far cheaper because it never shells out to du at all.
  • →Permission-denied directories print a "Permission denied" line to stderr for every one they hit — redirect with 2>/dev/null if you only want the size listing and are fine losing that warning.

Part by part

find . -type f
Regular files only, so directory entries do not appear alongside the files and distort the ranking.
-exec du -h {} +
The trailing plus batches many files into each du invocation rather than running one per file, which is dramatically faster on a large tree.
sort -rh
Reverse human-numeric sort: it understands that 2G is larger than 900M, which a plain sort does not.
head -n 10
Keeps the top ten. Without it the whole tree is printed, which on a real project is thousands of lines.

Common mistakes

  • find . -type f -exec du -h {} \; | sort -rh | head

    The semicolon runs du once per file, so a directory with fifty thousand files spawns fifty thousand processes. The plus form batches them and finishes in a fraction of the time.

    find . -type f -exec du -h {} + | sort -rh | head -n 10
  • find . -type f -exec du -h {} + | sort -r | head

    Without -h the sort is lexical, so 9K sorts above 2G because the character 9 comes after 2. The output looks plausible and the ranking is wrong.

  • du -h . | sort -rh | head

    Answers a different question — it ranks directories by total size rather than individual files. Both are useful; only one tells you which single file is enormous.

Questions

Does -h work on macOS?

Yes. BSD sort has supported -h for years, despite the persistent claim that it is GNU-only. If it genuinely is unavailable, use du -k and a plain numeric sort instead.

How do I skip node_modules?

Prune it: find . -path ./node_modules -prune -o -type f -exec du -h {} + is the usual form. Otherwise dependencies dominate the ranking and tell you nothing about your own files.

Why does the total differ from what my file manager reports?

du reports disk usage, which is rounded up to the filesystem block size, while a file manager often shows the apparent size. On many small files the difference adds up considerably.

Is there something simpler?

ncdu is an interactive browser for exactly this and is far more pleasant for exploring. This pipeline wins where you cannot install anything, which is most servers.

Related in Snippets