Disk Usage
Disk Quotas covered limiting how much space a user or group is allowed to use. But a quota only sets a limit — it doesn't show where space is actually running out on a filesystem right now. These are two independent questions: a quota answers "who is allowed how much," while disk usage answers "how much space is actually being used right now, and where." This article is dedicated to the second question — tools for checking available space and finding the biggest consumers.
What You Will Learn
By the end of this article you will be able to:
- explain why
df -handdu -shcan give different results; - explain the "open but deleted file" problem and its effect on disk usage;
- analyze a directory hierarchy step by step with
du --max-depth; - do a quick visual analysis with the interactive
ncdutool; - identify inode exhaustion with
df -i; - know how to find the largest file or directory.
df -h: the Filesystem-Level Overview
df (disk free) shows the total, used, and free space of mounted filesystems:
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 50G 42G 5.5G 89% /
/dev/vg_data/lv_app 20G 18G 1.1G 95% /mnt/app
tmpfs 2.0G 1.2M 2.0G 1% /run
-h (human-readable) shows bytes as GiB/MiB. df reads from filesystem metadata (the superblock), so the result appears instantly, with no delay, even on a very large filesystem.
To check one specific partition:
du -sh: Directory-Level Size
du (disk usage), on the other hand, calculates the actual space occupied by a specific directory or files, by counting through the actual files:
-s — show only the final summed total (without listing subdirectories separately), -h — human-readable format.
du genuinely scans the filesystem, so it can take time on large directories — unlike df, the result isn't instant.
Why df and du Don't Match
Sometimes df -h / reports "95% used," but summing up du -sh /* across every directory gives a noticeably smaller number. The most common reason for this is deleted-but-open files.
On Linux, when a file is deleted with rm, if that file is still open by some process (through a file descriptor), it isn't immediately removed — it's only removed from the directory (the list of file names). The disk blocks allocated for the file aren't freed until the process closes it.
rm removes the entry from the directory
│
▼
a process still holds the file open (via fd)
│
▼
disk blocks stay occupied — df reports this
du doesn't "see" the file, since it's no longer in the directory
This commonly happens, for example, when a log file has been rotated, but the service writing to it still holds the old file descriptor — until the service is restarted or the file is closed, the disk space isn't freed, even though du shows no large file at all.
Warning
A situation where "df says used, but du finds nothing" is very often caused by exactly this. The fix is finding deleted-but-open files with lsof — covered in depth in Disk-Full Troubleshooting.
du --max-depth: Step-by-Step Analysis
To find exactly which subdirectory is using the most space inside a large directory, limiting the depth is convenient:
Combining this result with sort for sorting by size is recommended:
sort -rh sorts human-readable values (1.2G, 340M) correctly, in descending order.
The next step is stepping into the largest directory and repeating the same command, narrowing down the problem area step by step — a process sometimes called "disk archaeology."
ncdu: Interactive Visual Analysis
Manually descending several levels with du --max-depth can be slow and inconvenient. ncdu (NCurses Disk Usage) provides an interactive, navigable terminal interface instead:
--- /var -----------------------------
1.2GiB [##########] /log
340MiB [### ] /cache
180MiB [## ] /lib
45MiB [ ] /tmp
The arrow keys navigate into a directory, and d deletes a file or directory directly. Compared to du, ncdu scans once and then lets you navigate the whole tree quickly — no rescanning each time.
Danger
Deleting with d inside ncdu is irreversible. Before blindly deleting files on a production server, always check what a file actually is (which service it belongs to, when it was created) — an important configuration or data file could be deleted by accident.
Running Out of Inodes: df -i
Even with free disk space, it may be impossible to create a file — because inodes have run out. Every file (regardless of size) occupies one inode, and a fixed number of inodes are allocated when a filesystem is created.
If IUse% is 100%, a new file can't be created even with free disk space — df -h doesn't show this at all, since it only counts bytes, not the number of files.
This situation typically shows up on systems creating millions of tiny files: session files, caches, mail spools, or a misconfigured temporary-file generator.
Finding the Largest File or Directory
Searching for files larger than a given size with find:
-xdev— limits the search to the current filesystem, without crossing into other mounted filesystems (e.g. NFS);-size +500M— files larger than 500 MiB.
Finding the top 10 largest directories, combining du and sort:
-a (all) — counts individual files as well, not just directories.
Practical Scenario: / Is 95% Full, but the Cause Is Unclear
Situation: df -h / shows the root partition at 95% used, but which directory is responsible is unknown.
Step 1. Confirm the overall state.
Step 2. Sort first-level directories.
Step 3. Go deeper into /var.
Step 4. Find the specific file inside /var/log.
Conclusion: the culprit is a single, uncontrollably grown debug.log file, likely because log rotation stopped working. Fully resolving the issue — clearing or removing the file, then fixing log rotation — continues as the central scenario in Disk-Full Troubleshooting.
Common Mistakes
Running du on the Whole / Without -x
Without -x (or --one-file-system), running du / also descends into other mounted filesystems (NFS, an external disk), giving an incorrect, inflated result:
Not Looking to du for the Cause When df Says "Full"
df only says "how much is used," not "what's using it." Finding the cause always requires digging in with du or ncdu.
Forgetting About Deleted-but-Open Files
If du's result and df's result don't match, this is often not a bug — a file has already been deleted, but a process still holds it open. This situation can't be identified with du/ncdu alone.
Not Checking for Inode Exhaustion
Seeing a "there's disk space, but files can't be created" error and concluding "there's enough space" from df -h alone, without checking df -i, is a common mistake.
Exercises
- Compare the output of
df -handdu -sh /*, determine whether there's a discrepancy, and explain why. - Use
du -h --max-depth=1 /var | sort -rhto find the three largest directories inside/var. - Install
ncdu, run it on/, and find the 5 largest directories interactively (viewing only, without deleting). - Check inode usage on your system with
df -iand note how it differs fromdf -h.
Verification criterion: given a filesystem showing 95% "used" by bytes but low inode usage, you should be able to state the next command that would find the responsible directory or file.
Summary
df -h gives a quick, filesystem-level overview, while du -sh counts the actual file sizes inside a directory — a mismatch between the two is often caused by deleted-but-open files. du --max-depth and ncdu help narrow down the culprit in a large directory hierarchy, step by step or interactively, while df -i reveals a file (inode), not byte, exhaustion problem. These tools work together with disk quotas: a quota shows who is allowed how much, while disk usage shows where space is actually going right now. The next article, Disk-Full Troubleshooting, combines both tools into a single practical procedure for resolving a real "disk is full" situation.