Sparse files

The problem

Run ls -lh on Docker’s virtual disk:

-rw-r--r--  1 al  staff  1.0T  Docker.raw

One terabyte? On a 460 GB drive? Something doesn’t add up.

Docker.raw is a sparse file. It has a logical size of 1 TiB (the maximum size Docker Desktop allocated for its virtual disk), but most of that space is empty — never written to. The filesystem only allocates blocks for the parts that actually contain data.

Apparent vs. on-disk size

apparent size:  1,099,511,627,776 bytes  (1.0 TiB)
on-disk size:          22,388,580,352 bytes  (20.9 GiB)

Most disk usage tools report the apparent size. This is misleading because it counts space that was never allocated.

The actual disk usage comes from the filesystem’s block allocation count:

stat -f "blocks=%b" Docker.raw
# blocks=43727696

# Actual size: 43727696 * 512 = 22,388,580,352 bytes = 20.9 GiB

How oops handles this

oops uses stat.blocks * 512 for every file, matching what du reports by default. This means:

  • Sparse files show their real footprint, not their inflated logical size
  • Compressed files (on APFS) may show smaller than their logical size
  • Regular files show the same size either way (block allocation ≈ logical size)

As a fallback, if blocks is zero (some virtual filesystems), oops falls back to the logical size.

Common sparse files on macOS

File Location Apparent Typical actual
Docker.raw ~/Library/Containers/com.docker.docker/Data/vms/0/data/ 1+ TiB 5–60 GiB
Time Machine snapshots Various Varies Much smaller
APFS sparse disk images .sparseimage files Configured max Actual content

Why this matters

Without block-level sizing, a tool can report your home directory as 1.3 TiB on a 460 GiB drive. With it, you get the real number — typically 200–300 GiB for a developer workstation. The inflated number makes every other size look proportionally tiny, hiding the directories that are actually consuming your disk.