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 countingdu --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 exploringdu -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 scanssudo 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