What Ncdu Is
Scope: the question ncdu answers, the scan-then-browse model, the two sizes it keeps for everything, versions 1.x and 2.x, where it runs, and the lab.
The question
Every disk eventually asks the same question: I'm full — what ate me? The honest answer is never one file. It is a tree: a downloads folder that kept every installer, a cache that grew a little every day for a year, photos saved twice. To find it you need sizes per directory, added up, biggest first — and then you need to walk down into the big ones and ask again.
ncdu (NCurses Disk Usage) does exactly that, in the terminal. It scans a tree once — reading directory entries and file metadata, never file contents — builds the totals in memory, and then lets you browse: descend into the directory that is eating the disk, sort, look closer, back out, descend somewhere else. The scan is the slow part; the browsing is instant, and it is a snapshot — chapter 2 shows how to refresh it when the disk moves under you.
The older tool du computes the same
totals, but prints them as one long table
and leaves the walking to you. ncdu is
best understood as du you can climb
around in. Chapter 8 puts them side by
side, and the neighbours are honest
competition: nothing in this guide needs
you to love ncdu, only to read a disk.
Two sizes for everything
ncdu tracks two sizes for every file, and much of this guide is the difference:
- Disk usage — the space the file actually takes on the disk: its content rounded up to whole filesystem blocks.
- Apparent size — the size of the content itself, what a program reading the file would see.
For most files they nearly agree. For a
few kinds they disagree wildly — a
one-byte file still costs a whole block,
and a sparse file can promise 100 MiB of
content while occupying nothing at all.
Chapter 3 takes the difference apart on
specimens built to show it. The main
screen keeps both totals in its footer at
all times, and the a key swaps which one
the listing sorts and shows.
Versions: 1.x and 2.x
ncdu exists in two generations. 1.x (the C original, still maintained as the "LTS" line — 1.22 is the current release) is what most Linux distributions package — the build machine ran the distro's 1.19. 2.x is a rewrite in Zig (this guide tested 2.9; 2.9.2 is current) with the same screen, the same keys and the same JSON export format, plus a compact binary export, zstd-compressed exports, parallel scanning, a config file, and a handful of extra options. Everything this guide teaches works in both unless a chapter says otherwise — and the places where the version matters are exactly the places chapter 6 lingers: an export written by 2.x in its new formats cannot be read by 1.x at all.
Check: the two builds, side by side on the build machine:
$ ncdu --version (the distro package)
ncdu 1.19
$ ncdu --version (the upstream static build)
ncdu 2.9
Where it runs
ncdu is a Unix terminal program. On Linux
it is one package install away
(apt install ncdu, dnf install ncdu,
and so on); the upstream site also ships
static binaries that run anywhere. On
macOS it installs with Homebrew
(brew install ncdu) and behaves the
same, with one local wrinkle — Apple's
firmlinks — flagged in chapter 9. There
is no official Windows build (an old
third-party Cygwin-based one exists): on
Windows the realistic routes are WSL
(where ncdu works on the Linux side) or a
different tool entirely — chapter 8 names
the Windows natives honestly rather than
pretending. Inside ncdu, nothing cares
which Unix it is: the keys, flags and
export format in this guide were captured
on Linux and are the same interface
elsewhere.
The lab
Everything in this guide happens in one specimen home directory, built by a script so your copy is identical to the one in the captures:
$ sh build-tree.sh homedir
built /path/to/homedir
The script is in examples/, beside a
lab-notes.txt that describes every
specimen and why it exists: installers of
12, 8 and 5 MiB in Downloads, 24 MiB of
video, a cache of twenty small files and
one 4 MiB blob, a hardlinked photograph
kept under two names, a 100 MiB sparse
disk image that occupies nothing, a file
with a space in its name, a one-byte file
in a 4096-byte block, and two symlinks.
Fifty-nine entries in all; every name
invented, every size deliberate.
Here is the whole guide in one screen —
the first thing ncdu shows after scanning
the lab (captured from 1.19; the working
transcripts are kept in ncdu-lab/):
ncdu 1.19 ~ Use the arrow keys to navigate, press ? for help
--- /home/.../homedir --------------------------------
34.0 MiB [##############] /Videos
25.0 MiB [########## ] /Downloads
5.8 MiB [## ] /Pictures
4.1 MiB [# ] /.cache
12.0 KiB [ ] /Documents
4.0 KiB [ ] /deep
@ 4.0 KiB [ ] link-to-notes
@ 4.0 KiB [ ] link-to-videos
4.0 KiB [ ] tiny.txt
0.0 B [ ] /vm-images
e 0.0 B [ ] /empty-dir
Total disk usage: 68.9 MiB Apparent size: 168.8 MiB Items: 58
Videos is the problem, Downloads is next,
and vm-images — the directory holding a
100 MiB file — sits at the bottom showing
zero, because the list is sorted by disk
usage and that file uses no disk. The
footer keeps the score: 68.9 MiB actually
spent, 168.8 MiB of content claimed. The
100 MiB difference is one sparse file, and
by the end of chapter 3 you will be able
to prove it three different ways.
One last habit to form now: the lab is
the specimen, not your disk. Every scan,
export and — in chapter 5 — deletion in
this guide happens inside homedir/ or a
throwaway copy of it. Run ncdu on your
real home directory freely for looking; it
cannot change anything by looking. But
read chapter 5 before you press d
anywhere that matters.