Linux Disk Usage: df, du, and ncdu

Running out of disk space in production isn't just inconvenient—it's catastrophic. Applications crash, databases corrupt, logs stop writing, and deployments fail. I've seen a full `/var` partition...

Key Insights

  • df shows filesystem-level disk usage and is your first stop for overall capacity checks, while du drills into directory structures to find what’s actually consuming space
  • ncdu provides an interactive, visual interface that makes exploring disk usage faster and more intuitive than chaining together du and sort commands
  • Deleted files held open by running processes won’t free disk space until those processes restart—a common gotcha that df reveals but du won’t show

Why Disk Usage Monitoring Matters

Running out of disk space in production isn’t just inconvenient—it’s catastrophic. Applications crash, databases corrupt, logs stop writing, and deployments fail. I’ve seen a full /var partition bring down an entire Kubernetes cluster because Docker couldn’t write container metadata. The worst part? It’s completely preventable.

Understanding disk usage tools isn’t optional knowledge for system administrators and developers. These three commands—df, du, and ncdu—form the foundation of disk space troubleshooting. Each serves a distinct purpose, and knowing when to use which tool will save you hours of frustration when that 3 AM alert fires.

The df Command: Filesystem-Level Overview

The df (disk free) command reports filesystem-level disk space usage. It shows you the big picture: how much space is available on each mounted filesystem. This is your starting point for any disk investigation.

The most common usage is with the -h flag for human-readable output:

df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        50G   42G  5.5G  89% /
/dev/sdb1       500G  380G  120G  76% /var
tmpfs           7.8G  1.2M  7.8G   1% /run

This immediately tells you which filesystems are approaching capacity. The Use% column is what you’re watching—anything above 85% deserves attention.

To check a specific filesystem or directory, pass it as an argument:

df -h /var/log
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdb1       500G  380G  120G  76% /var

One critical but often overlooked metric is inode usage. You can run out of inodes before running out of disk space, especially with millions of small files:

df -i
Filesystem      Inodes  IUsed   IFree IUse% Mounted on
/dev/sda1      3276800 298456 2978344    9% /
/dev/sdb1     32768000 31500000 1268000   97% /var

That 97% inode usage on /var is a red flag. Even with available disk space, you can’t create new files.

To see filesystem types, which helps identify network mounts or special filesystems:

df -Th
Filesystem     Type      Size  Used Avail Use% Mounted on
/dev/sda1      ext4       50G   42G  5.5G  89% /
/dev/sdb1      xfs       500G  380G  120G  76% /var
nfs-server:/   nfs4      2.0T  1.5T  500G  75% /mnt/shared

The du Command: Directory-Level Analysis

While df shows filesystem totals, du (disk usage) reveals what’s actually consuming that space. This is where you start hunting for the culprits.

To get a summary of top-level directories:

du -sh /var/*
8.0K    /var/backups
250G    /var/log
4.0K    /var/mail
120G    /var/lib
1.5G    /var/cache

Immediately you see /var/log is the problem. The -s flag summarizes each directory, and -h makes it human-readable.

To drill deeper with controlled depth:

du -h --max-depth=2 /var/log
150G    /var/log/application
80G     /var/log/nginx
20G     /var/log/system
250G    /var/log

This limits recursion to two levels, preventing overwhelming output on deep directory trees.

To find the largest files and directories across your entire system:

du -ah /var | sort -rh | head -20
250G    /var/log
150G    /var/log/application
80G     /var/log/nginx
75G     /var/log/nginx/access.log
70G     /var/log/application/debug.log

The -a flag includes files, not just directories. Piping through sort -rh (reverse, human-readable) and head -20 gives you the top 20 space consumers.

Sometimes you want to exclude certain patterns:

du -sh --exclude='*.log' /var

This is useful when you know logs are large but want to see what else is taking space.

The ncdu Command: Interactive Disk Usage Explorer

ncdu (NCurses Disk Usage) is a game-changer. It provides an interactive, visual interface for exploring disk usage that’s far more efficient than repeatedly running du commands.

First, install it:

# Debian/Ubuntu
apt install ncdu

# RHEL/CentOS
yum install ncdu

# macOS
brew install ncdu

Basic usage scans a directory and opens an interactive interface:

ncdu /var

The interface shows a sorted list of directories and files by size. You can navigate with arrow keys, press Enter to descend into directories, and press n to sort by name or d to delete files directly.

The display looks like this:

ncdu 1.15 ~ Use the arrow keys to navigate, press ? for help
--- /var --------------------------------------------------------
  250.0 GiB [##########] /log
  120.0 GiB [####      ] /lib
    1.5 GiB [          ] /cache
    8.0 KiB [          ] /backups

To exclude mounted filesystems (useful when scanning from root):

ncdu -x /

The -x flag stays on the same filesystem, avoiding network mounts or other partitions.

For large directories, you can save the scan results and browse them later:

ncdu -o /tmp/var-scan.ncdu /var
ncdu -f /tmp/var-scan.ncdu

This is invaluable when scanning takes significant time—you can disconnect from the server and analyze results locally.

Practical Comparison: When to Use Each Tool

Quick health check of all filesystems:

df -h

Use df when you need a 30,000-foot view. It’s fast, shows all mounted filesystems, and immediately highlights capacity issues.

Finding what’s filling a specific partition:

du -sh /var/* | sort -rh

Use du when df shows a filesystem is full and you need to identify the guilty directories. It’s scriptable and perfect for automation.

Interactive cleanup session:

ncdu /var/log

Use ncdu when you need to explore interactively, especially during cleanup operations. The visual interface makes it easy to navigate deep directory structures and identify deletion candidates.

Real-World Troubleshooting Workflow

Here’s how I investigate a “disk full” alert:

Step 1: Identify the full filesystem

df -h

Step 2: Check for inode exhaustion

df -i

Step 3: Find top-level space consumers

du -sh /<full-filesystem>/* | sort -rh | head -10

Step 4: Check for deleted files held open

lsof | grep deleted | grep <filesystem>

This is critical. A process can keep a deleted file’s disk space allocated until it releases the file handle. Restarting the process frees the space.

Step 5: Interactive exploration

ncdu /<problematic-directory>

Automated monitoring script:

#!/bin/bash
THRESHOLD=85

df -h | awk 'NR>1 {gsub(/%/,"",$5); if($5 > '$THRESHOLD') print $0}' | while read line; do
    FILESYSTEM=$(echo $line | awk '{print $1}')
    USAGE=$(echo $line | awk '{print $5}')
    MOUNT=$(echo $line | awk '{print $6}')
    
    echo "ALERT: $FILESYSTEM mounted on $MOUNT is ${USAGE}% full"
    du -sh $MOUNT/* | sort -rh | head -5
done

This script checks all filesystems and reports top consumers when usage exceeds 85%.

Best Practices and Tips

Monitor proactively, not reactively. Set up automated alerts before you hit 90% capacity. Recovering from a full disk is harder than preventing it.

Watch inode usage on filesystems with many small files. Mail servers, cache directories, and build systems are common culprits.

Remember the deleted-but-open-file gotcha. Always check lsof when df and du don’t match. I’ve seen 100GB “disappear” because nginx was holding deleted log files open.

Use ncdu for one-off investigations, du for scripts. Don’t try to parse ncdu output—it’s meant for humans. Use du in cron jobs and monitoring scripts.

Exclude network filesystems when scanning from root. Use ncdu -x / or du -x / to avoid traversing NFS mounts that might be slow or unreachable.

Rotate logs before they fill the disk. Configure logrotate properly. It’s easier than emergency cleanup at 2 AM.

Here’s a simple cron job for weekly disk usage reports:

# /etc/cron.weekly/disk-usage-report
#!/bin/bash
{
    echo "Disk Usage Report - $(date)"
    echo "================================"
    df -h
    echo ""
    echo "Top 10 Space Consumers:"
    du -sh /var/* /home/* 2>/dev/null | sort -rh | head -10
} | mail -s "Weekly Disk Usage Report" admin@example.com

These three tools—df, du, and ncdu—cover 99% of disk usage scenarios. Master them, understand their strengths, and you’ll never be caught off-guard by a full disk again.

Liked this? There's more.

Every week: one practical technique, explained simply, with code you can use immediately.