Skip to main content

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 --inodes counts files instead of bytes, revealing directories flooded with tiny files.
  • Works without an index — unlike locate or find database-backed tools, du reads 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 -h first to confirm which filesystem is full, then du -h --max-depth=1 /mount/point to rank directories, then recurse into the largest one.
  • Use -s while exploring — du -sh PATH gives a single summary number and runs faster than a full tree walk.
  • Use --max-depth to control output — start at depth 1 and only go deeper when you need to.
  • Treat caches separately — measure them with du -sh wp-content/cache but consider excluding them (--exclude=cache) when diagnosing persistent growth.
  • Check inodes too — if df -i shows high inode usage, use du --inodes -d 2 /var/www/html to find the inode-heavy directories.
  • Use -x on 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 compare du runs across incidents.
  • Schedule a daily report — trend the output of du -h --max-depth=2 wp-content | sort -hr to catch growth before it causes an outage.

Tips & Strategy​

Start with a two-command triage sequence
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.

Sort by size to find the biggest offender instantly
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.

Use * with caution — it misses hidden directories
du -sh * | sort -h # misses .cache, .composer etc.
du -sh .[!.]* * | sort -h # includes dot-directories
Use -t to reduce noise on large trees
du -h --max-depth=2 -t 100M wp-content

Only entries larger than 100 MB appear — everything smaller is silently filtered out.

Bytes output for automation and alerting scripts
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.

MetricWhat it measuresCommandWhen it matters
Disk usage (default)Blocks actually allocated on diskdu -sh PATHCapacity planning and "disk is full" incidents
Apparent sizeLogical file size the file claims to bedu -sh --apparent-size PATHSparse files, database dumps, comparing compression ratios

Common WordPress VPS Paths to Monitor​

PathWhat grows thereTypical reason to check
wp-content/uploads/Media libraryLarge images, backups stored in uploads, old year/month directories
wp-content/plugins/PluginsPlugin bloat, unused plugins, vendor bundles
wp-content/themes/ThemesOld inactive themes, large theme assets
wp-content/cache/CachePage cache, image optimization cache, temp files
/var/log/System and app logsMisconfigured log level, stale rotated logs
/var/lib/mysql/Database filesDatabase growth, large tables, binary logs
/backups/ (or similar)Backup archivesRetention 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​

OptionLong FormDescriptionExample
-h--human-readableHuman-readable sizes (powers of 1024: K, M, G)du -h wp-content
--si--siHuman-readable sizes (powers of 1000: kB, MB, GB)du --si -sh /var/log
-s--summarizePrint only a total for each argumentdu -sh wp-content/uploads
--max-depth=N--max-depth=NPrint totals only for directories N levels deepdu -h --max-depth=1 wp-content
-d N--max-depth=NAlias for --max-depthdu -hd 2 /var/www/html
-a--allInclude files, not just directoriesdu -ah wp-content
-c--totalPrint a grand total line at the enddu -ch /var/www/html
-S--separate-dirsExclude subdirectory totals from parentdu -Sh --max-depth=1 wp-content
--time--timeShow last modification timedu -h --time wp-content/uploads
--time=WORD--time=WORDChoose time field: atime, ctime, use, statusdu -h --time=atime wp-content
--time-style=STYLE--time-style=STYLEFormat time output: long-iso, full-iso, +FORMATdu -h --time --time-style=long-iso wp-content
--inodes--inodesCount inodes instead of block usagedu --inodes -d 1 wp-content
--apparent-size--apparent-sizeShow logical file size instead of disk blocksdu -sh --apparent-size db.sql
-b--bytesByte output — equivalent to --apparent-size --block-size=1du -sb wp-content/uploads
-B SIZE--block-size=SIZEScale all sizes by SIZE before printingdu -s -B1M wp-content
-k1 KiB blocks — equivalent to --block-size=1Kdu -k wp-content
-m1 MiB blocks — equivalent to --block-size=1Mdu -m wp-content
-t SIZE--threshold=SIZEOmit entries smaller than SIZE (use +SIZE for above threshold)du -h -t 100M wp-content
--exclude=PATTERN--exclude=PATTERNSkip entries matching PATTERN (shell glob)du -h --max-depth=2 wp-content --exclude=cache
-X FILE--exclude-from=FILERead exclude patterns from FILE (one per line)du -h --exclude-from=exclude.txt wp-content
-x--one-file-systemDo not cross filesystem boundariessudo du -xh --max-depth=1 /
-L--dereferenceFollow all symbolic linksdu -Lh /var/www/html
-D / -H--dereference-argsFollow symlinks only when they are CLI argumentsdu -Dh /symlink/path
-P--no-dereferenceNever follow symlinks (default)du -Ph wp-content
-l--count-linksCount hard-linked files multiple timesdu -lh wp-content
-0--nullEnd output lines with NUL instead of newlinedu -0 wp-content | xargs -0 ...
--files0-from=F--files0-from=FRead NUL-terminated input paths from file Fdu --files0-from=paths.txt

Practical Use Cases​

1. Current folder total​

du-current-folder-total.sh
du -sh .
example-output-du-current-folder.txt
150M .

Use case: Quick total for wherever you are right now.


2. Uploads directory total​

du-uploads-total.sh
du -sh wp-content/uploads
example-output-du-uploads-total.txt
2.1G wp-content/uploads

Use case: Monitor media library growth.


3. Breakdown by immediate subdirectory​

du-breakdown-depth-1-wp-content.sh
du -h --max-depth=1 wp-content
example-output-du-breakdown-wp-content.txt
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-sort-largest-folders.sh
du -h --max-depth=1 wp-content | sort -hr
example-output-du-sort-h.txt
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-top-20-largest-directories.sh
du -h --max-depth=2 /var/www/html | sort -hr | head -20
example-output-du-top-20.txt
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-include-files-audit.sh
du -ah /var/www/html
example-output-du-include-files.txt
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-grand-total.sh
du -ch /var/www/html
example-output-du-grand-total.txt
...
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-separate-dirs.sh
du -Sh --max-depth=1 wp-content
example-output-du-separate-dirs.txt
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-show-modification-time.sh
du -h --time --time-style=long-iso wp-content/uploads
example-output-du-time.txt
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-threshold-100m.sh
du -h --max-depth=2 -t 100M wp-content
example-output-du-threshold.txt
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-wp-content-excluding-cache.sh
du -h --max-depth=2 wp-content --exclude=cache
example-output-du-exclude-cache.txt
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:

du-exclude-patterns.txt
cache
*.tmp
*.zip
node_modules

Run du with the exclude file:

du-exclude-from-file.sh
du -h --max-depth=2 wp-content --exclude-from=du-exclude-patterns.txt
example-output-du-exclude-from-file.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-inode-count-by-dir.sh
du --inodes -d 1 /var/www/html
example-output-du-inodes.txt
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-db-dump.sh
du --apparent-size -h db.sql
example-output-du-apparent-size.txt
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-bytes-for-scripting.sh
du -sb wp-content/uploads
example-output-du-bytes.txt
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-force-mib-units.sh
du -s -B1M wp-content/uploads
example-output-du-block-size.txt
2100 wp-content/uploads

Use case: Standardize units across multiple servers when pasting values into tickets or runbooks.


17. Root overview without crossing filesystems​

du-root-one-filesystem-depth-1.sh
sudo du -xh --max-depth=1 /
example-output-du-root-x-depth-1.txt
...
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-uploads-by-year-month.sh
du -h --max-depth=2 wp-content/uploads
example-output-du-uploads-by-year.txt
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​

du-var-log-breakdown-sort.sh
sudo du -h --max-depth=1 /var/log | sort -h
example-output-du-var-log-breakdown.txt
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)​

du-mysql-data-dir.sh
sudo du -sh /var/lib/mysql
example-output-du-mysql-data-dir.txt
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-decimal-units-si.sh
du -sh --si /var/log
example-output-du-si.txt
839MB /var/log

Use case: Compare du output to cloud provider dashboards that display decimal GB/MB values.


daily-du-report.sh
#!/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"
example-output-daily-du-report.txt
Wrote report: /tmp/du-wp-content-2026-03-01.txt

Example report excerpt:

du-wp-content-2026-03-01.txt (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​

ToolLevelAnswersBest Used For
dfFilesystem"How much space is left on this partition?"Capacity monitoring, disk alerts
duDirectory tree"Which folder is consuming the space?"Finding the culprit after df warns you

Recommended triage sequence:

  1. df -h — confirm which filesystem is running out of bytes.
  2. df -i — rule out inode exhaustion.
  3. du -h --max-depth=1 /mount/point — rank directories by size.
  4. Drill into the largest directory until you find the offending folder.

Hands-On Practice​

Quick Lab (5 Exercises)​

  1. Run df -h and identify which filesystem is closest to full.
  2. In your WordPress root, run du -h --max-depth=1 wp-content.
  3. Pick the biggest subfolder and drill down: du -h --max-depth=2 PATH.
  4. Compare disk usage vs apparent size for a large file: du -h FILE vs du -h --apparent-size FILE.
  5. 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-top-5-wp-content.sh
du -h --max-depth=2 wp-content | sort -hr | head -5

Mini Quiz​

  1. What does du measure by default, and how does that differ from ls -lh?
  2. Which option prints a single summary total for a path?
  3. Which option limits how many directory levels deep du reports?
  4. When would you use --apparent-size instead of the default?
  5. What does du --inodes help you diagnose?
  6. Why is du -xh --max-depth=1 / safer than du -h --max-depth=1 / when scanning the root?
  7. How would you use du to exclude the cache directory from a wp-content scan?
  8. What flag produces byte output suitable for use in a shell script comparison?

Cheat Sheet
du-cheat-sheet.sh
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

What's Next​