du — Disk Usage Analyzer
du (disk usage) estimates disk usage for files and directories by walking a path and summing the blocks used on disk. Use it after df identifies which filesystem is full — du answers the follow-up question: which directory is responsible? It is the go-to tool for pinpointing WordPress folders (uploads, caches, plugins, logs, backups) that are consuming the most space. By default it reports actual disk block usage; add --apparent-size when you need the logical file size instead.
System Check
which du # Expected: /usr/bin/du
du --version # Recommended: GNU coreutils 8.x+
Benefits
- Pinpoints disk hogs — drill from the root partition down to the exact subdirectory consuming space.
- Inode counting —
du --inodescounts files instead of bytes, revealing directories flooded with tiny files. - Works without an index — unlike
locateorfinddatabase-backed tools,dureads the filesystem directly. - Scriptable — byte output (
-sb) and threshold filtering (-t) make it easy to integrate into monitoring and alerting scripts. - Flexible units — switch between human-readable, SI decimal, raw bytes, or fixed block sizes (
-BM) to match your reporting format. - Prevents downtime — tracking growth trends in uploads, caches, and logs gives you advance warning before hitting 100% disk usage.
Best Practices
- Start broad, then drill down — run
df -hfirst to confirm which filesystem is full, thendu -h --max-depth=1 /mount/pointto rank directories, then recurse into the largest one. - Use
-swhile exploring —du -sh PATHgives a single summary number and runs faster than a full tree walk. - Use
--max-depthto control output — start at depth 1 and only go deeper when you need to. - Treat caches separately — measure them with
du -sh wp-content/cachebut consider excluding them (--exclude=cache) when diagnosing persistent growth. - Check inodes too — if
df -ishows high inode usage, usedu --inodes -d 2 /var/www/htmlto find the inode-heavy directories. - Use
-xon root scans —sudo du -xh --max-depth=1 /stays on one filesystem and avoids crossing mounted backup volumes or network mounts. - Prefer
--time-style=long-iso— consistent timestamps make it easier to compareduruns across incidents. - Schedule a daily report — trend the output of
du -h --max-depth=2 wp-content | sort -hrto catch growth before it causes an outage.
Tips & Strategy
df -h # Step 1 — which filesystem is running out of space?
du -h --max-depth=1 /mount/point # Step 2 — which directory is consuming it?
Run step 1 first. Only run step 2 on the specific mount point that is filling up.
du -h --max-depth=2 /var/www/html | sort -hr | head -20
Piping into sort -hr (human-readable, reverse) puts the largest entry at the top — no manual scanning needed.
* with caution — it misses hidden directoriesdu -sh * | sort -h # misses .cache, .composer etc.
du -sh .[!.]* * | sort -h # includes dot-directories
-t to reduce noise on large treesdu -h --max-depth=2 -t 100M wp-content
Only entries larger than 100 MB appear — everything smaller is silently filtered out.
du -sb wp-content/uploads
Returns an exact integer (no units) suitable for threshold comparisons in bash scripts, cron jobs, and monitoring systems.
Disk Usage vs Apparent Size
du reports disk block usage by default. That can differ from the logical file size shown by ls -lh.
| Metric | What it measures | Command | When it matters |
|---|---|---|---|
| Disk usage (default) | Blocks actually allocated on disk | du -sh PATH | Capacity planning and "disk is full" incidents |
| Apparent size | Logical file size the file claims to be | du -sh --apparent-size PATH | Sparse files, database dumps, comparing compression ratios |
Common WordPress VPS Paths to Monitor
| Path | What grows there | Typical reason to check |
|---|---|---|
wp-content/uploads/ | Media library | Large images, backups stored in uploads, old year/month directories |
wp-content/plugins/ | Plugins | Plugin bloat, unused plugins, vendor bundles |
wp-content/themes/ | Themes | Old inactive themes, large theme assets |
wp-content/cache/ | Cache | Page cache, image optimization cache, temp files |
/var/log/ | System and app logs | Misconfigured log level, stale rotated logs |
/var/lib/mysql/ | Database files | Database growth, large tables, binary logs |
/backups/ (or similar) | Backup archives | Retention drift, duplicate archives |
Syntax & Options Reference
Core Syntax
du [OPTION]... [FILE]...
OPTION— controls formatting, traversal depth, unit output, and filtering.FILE— file or directory to analyze. Defaults to.(current directory) if omitted.
Complete Options Table
| Option | Long Form | Description | Example |
|---|---|---|---|
-h | --human-readable | Human-readable sizes (powers of 1024: K, M, G) | du -h wp-content |
--si | --si | Human-readable sizes (powers of 1000: kB, MB, GB) | du --si -sh /var/log |
-s | --summarize | Print only a total for each argument | du -sh wp-content/uploads |
--max-depth=N | --max-depth=N | Print totals only for directories N levels deep | du -h --max-depth=1 wp-content |
-d N | --max-depth=N | Alias for --max-depth | du -hd 2 /var/www/html |
-a | --all | Include files, not just directories | du -ah wp-content |
-c | --total | Print a grand total line at the end | du -ch /var/www/html |
-S | --separate-dirs | Exclude subdirectory totals from parent | du -Sh --max-depth=1 wp-content |
--time | --time | Show last modification time | du -h --time wp-content/uploads |
--time=WORD | --time=WORD | Choose time field: atime, ctime, use, status | du -h --time=atime wp-content |
--time-style=STYLE | --time-style=STYLE | Format time output: long-iso, full-iso, +FORMAT | du -h --time --time-style=long-iso wp-content |
--inodes | --inodes | Count inodes instead of block usage | du --inodes -d 1 wp-content |
--apparent-size | --apparent-size | Show logical file size instead of disk blocks | du -sh --apparent-size db.sql |
-b | --bytes | Byte output — equivalent to --apparent-size --block-size=1 | du -sb wp-content/uploads |
-B SIZE | --block-size=SIZE | Scale all sizes by SIZE before printing | du -s -B1M wp-content |
-k | 1 KiB blocks — equivalent to --block-size=1K | du -k wp-content | |
-m | 1 MiB blocks — equivalent to --block-size=1M | du -m wp-content | |
-t SIZE | --threshold=SIZE | Omit entries smaller than SIZE (use +SIZE for above threshold) | du -h -t 100M wp-content |
--exclude=PATTERN | --exclude=PATTERN | Skip entries matching PATTERN (shell glob) | du -h --max-depth=2 wp-content --exclude=cache |
-X FILE | --exclude-from=FILE | Read exclude patterns from FILE (one per line) | du -h --exclude-from=exclude.txt wp-content |
-x | --one-file-system | Do not cross filesystem boundaries | sudo du -xh --max-depth=1 / |
-L | --dereference | Follow all symbolic links | du -Lh /var/www/html |
-D / -H | --dereference-args | Follow symlinks only when they are CLI arguments | du -Dh /symlink/path |
-P | --no-dereference | Never follow symlinks (default) | du -Ph wp-content |
-l | --count-links | Count hard-linked files multiple times | du -lh wp-content |
-0 | --null | End output lines with NUL instead of newline | du -0 wp-content | xargs -0 ... |
--files0-from=F | --files0-from=F | Read NUL-terminated input paths from file F | du --files0-from=paths.txt |
Practical Use Cases
1. Current folder total
du -sh .
150M .
Use case: Quick total for wherever you are right now.
2. Uploads directory total
du -sh wp-content/uploads
2.1G wp-content/uploads
Use case: Monitor media library growth.
3. Breakdown by immediate subdirectory
du -h --max-depth=1 wp-content
450M wp-content/plugins
2.1G wp-content/uploads
300M wp-content/cache
2.9G wp-content
Use case: Identify which subfolder is consuming the most space — the final line is the total for the directory itself.
4. Sort largest directories
du -h --max-depth=1 wp-content | sort -hr
2.9G wp-content
2.1G wp-content/uploads
450M wp-content/plugins
300M wp-content/cache
Use case: Immediately see the biggest offender at the top without manual scanning.
5. Top 20 largest directories two levels deep
du -h --max-depth=2 /var/www/html | sort -hr | head -20
2.1G /var/www/html/wp-content/uploads
450M /var/www/html/wp-content/plugins
300M /var/www/html/wp-content/cache
...
Use case: Full-tree triage to find the biggest directories across the entire WordPress install.
6. Include files as well as directories
du -ah /var/www/html
8.0K /var/www/html/wp-config.php
2.1G /var/www/html/wp-content/uploads
Use case: Deep audit when you need to find large individual files, not just directory totals.
7. Grand total with -c
du -ch /var/www/html
...
2.9G total
Use case: Get a definitive total for the entire WordPress tree.
8. Separate a directory's own files from its subdirectories
du -Sh --max-depth=1 wp-content
450M wp-content/plugins
2.1G wp-content/uploads
300M wp-content/cache
12M wp-content
Use case: The final wp-content line shows only files directly inside wp-content/ (not totals from subfolders) — useful to see if growth is inside subdirectories or in the directory's own files.
9. Show modification time alongside size
du -h --time --time-style=long-iso wp-content/uploads
2.1G 2025-10-01 12:00 wp-content/uploads
Use case: Identify stale directories that haven't changed in months vs actively growing ones.
10. Filter by size threshold
du -h --max-depth=2 -t 100M wp-content
2.1G wp-content/uploads
450M wp-content/plugins
300M wp-content/cache
Use case: Remove noise when a directory contains many small subfolders — only show directories above 100 MB.
11. Exclude a directory from the output
du -h --max-depth=2 wp-content --exclude=cache
2.1G wp-content/uploads
450M wp-content/plugins
...
Use case: Temporarily exclude the cache directory so you can focus on persistent disk growth rather than cache fluctuations.
12. Exclude multiple patterns from a file
Create an exclude list:
cache
*.tmp
*.zip
node_modules
Run du with the exclude file:
du -h --max-depth=2 wp-content --exclude-from=du-exclude-patterns.txt
2.1G wp-content/uploads
450M wp-content/plugins
...
Use case: Ignore multiple categories of temporary or volatile data in one go.
13. Inode count by subdirectory
du --inodes -d 1 /var/www/html
150 wp-content/plugins
4200 wp-content/uploads
Use case: Identify directories flooded with tiny files (thumbnails, transients, session files) that cause inode exhaustion.
14. Apparent size (logical file size)
du --apparent-size -h db.sql
1.2G db.sql
Use case: Compare the logical size of a database dump against what it actually consumes on disk — helpful for sparse files and compressed output.
15. Byte output for scripts
du -sb wp-content/uploads
2254857830 wp-content/uploads
Use case: Returns an exact integer — perfect for threshold comparisons in monitoring scripts and cron jobs.
16. Force a specific block size (MiB)
du -s -B1M wp-content/uploads
2100 wp-content/uploads
Use case: Standardize units across multiple servers when pasting values into tickets or runbooks.
17. Root overview without crossing filesystems
sudo du -xh --max-depth=1 /
...
1.2G /var
3.8G /home
...
Use case: Get a high-level disk map for the entire VPS without accidentally traversing mounted backup volumes or NFS shares.
18. Uploads breakdown by year and month
du -h --max-depth=2 wp-content/uploads
80M wp-content/uploads/2025/10
500M wp-content/uploads/2025
2.1G wp-content/uploads
Use case: Identify which campaign month or year is responsible for disproportionate media growth.
19. Break down /var/log by service
sudo du -h --max-depth=1 /var/log | sort -h
50M /var/log/nginx
120M /var/log/mysql
800M /var/log
Use case: Find which service is generating the most logs and whether log rotation is working.
20. Measure database storage (MariaDB/MySQL)
sudo du -sh /var/lib/mysql
3.5G /var/lib/mysql
Use case: Confirm whether disk growth is driven by database files, binary logs, or WordPress uploads.
21. Decimal units for dashboard comparison
du -sh --si /var/log
839MB /var/log
Use case: Compare du output to cloud provider dashboards that display decimal GB/MB values.
22. Create a daily du report for trending
#!/usr/bin/env bash
set -euo pipefail
WP_ROOT="/var/www/html"
OUT="/tmp/du-wp-content-$(date +%F).txt"
du -h --max-depth=2 "$WP_ROOT/wp-content" | sort -hr > "$OUT"
printf 'Wrote report: %s\n' "$OUT"
Wrote report: /tmp/du-wp-content-2026-03-01.txt
Example report excerpt:
2.1G /var/www/html/wp-content/uploads
450M /var/www/html/wp-content/plugins
300M /var/www/html/wp-content/cache
...
Use case: Track growth over time and detect drift before it becomes an incident.
du vs df — When to Use Which
| Tool | Level | Answers | Best Used For |
|---|---|---|---|
df | Filesystem | "How much space is left on this partition?" | Capacity monitoring, disk alerts |
du | Directory tree | "Which folder is consuming the space?" | Finding the culprit after df warns you |
Recommended triage sequence:
df -h— confirm which filesystem is running out of bytes.df -i— rule out inode exhaustion.du -h --max-depth=1 /mount/point— rank directories by size.- Drill into the largest directory until you find the offending folder.
Hands-On Practice
Quick Lab (5 Exercises)
- Run
df -hand identify which filesystem is closest to full. - In your WordPress root, run
du -h --max-depth=1 wp-content. - Pick the biggest subfolder and drill down:
du -h --max-depth=2 PATH. - Compare disk usage vs apparent size for a large file:
du -h FILEvsdu -h --apparent-size FILE. - If uploads are large, break them down by year and month:
du -h --max-depth=2 wp-content/uploads.
Task: Build a Space Report One-Liner
Write a single du command that shows the top 5 directories consuming space inside wp-content, sorted largest first, in human-readable format.
Solution
du -h --max-depth=2 wp-content | sort -hr | head -5
Mini Quiz
- What does
dumeasure by default, and how does that differ fromls -lh? - Which option prints a single summary total for a path?
- Which option limits how many directory levels deep
dureports? - When would you use
--apparent-sizeinstead of the default? - What does
du --inodeshelp you diagnose? - Why is
du -xh --max-depth=1 /safer thandu -h --max-depth=1 /when scanning the root? - How would you use
duto exclude the cache directory from a wp-content scan? - What flag produces byte output suitable for use in a shell script comparison?
Cheat Sheet
du -sh . # Current folder total
du -sh wp-content/uploads # Uploads total
du -h --max-depth=1 wp-content # Breakdown by immediate subfolders
du -hd 2 /var/www/html # Breakdown two levels deep
du -h --max-depth=2 /var/www/html | sort -hr | head -20 # Top 20 largest
du -ch /var/www/html # Grand total
du -ah /var/www/html # Include files (not just dirs)
du -sh * | sort -h # Sort current folder totals
du -sh .[!.]* * | sort -h # Include hidden directories
du --inodes -d 2 /var/www/html # Inode counts
du --apparent-size -h db.sql # Logical file size
du -sb wp-content/uploads # Exact bytes for scripts
du -s -B1M wp-content # Force MiB units
du -h -t 100M --max-depth=2 wp-content # Only entries > 100 MB
du -h --exclude=cache --max-depth=2 wp-content # Exclude cache
sudo du -xh --max-depth=1 / # Root overview (one filesystem)
sudo du -sh /var/log # Log partition total
sudo du -sh /var/lib/mysql # Database storage total
sudo du -h --max-depth=1 /var/log | sort -h # Log breakdown by service