df
read-onlyReports free and used space per mounted filesystem.
- Command
- adb shell df
- Commands
- Files and storage
- Risk
- read-only
Syntax
df [-k] [-h] [-H] [-P] [-i] [<path>]Flags and arguments
| Token | Meaning |
|---|---|
| -k | 1024-byte blocks, and the flag that pins the header to a label you can rely on. |
| -h | Human-readable, base 1024. |
| -H | Human-readable, base 1000. |
| -P | POSIX output: 512-byte blocks, and the percentage column is named Capacity. |
| -i | Count inodes instead of bytes. The columns then hold inode counts. |
| -t <type> | Restrict the table to filesystems of one type. Worth having on Android, where an unfiltered listing buries the two partitions you care about under dozens of `tmpfs` and overlay mounts. |
| -a | Include the pseudo-filesystems that are hidden by default. Reach for it when a mount you expected is simply missing from the ordinary listing, before concluding it was never mounted. |
Examples
df -k /dataFree space on the userdata partition, in KiB.
df -kEvery mounted filesystem.
df -h /dataQuick to read by eye; not a number to compute with.
df -k /data /sdcardThe two rows that matter on a phone, in one call, with the unit declared once in the shared header.
df -k -aEverything, pseudo-filesystems included, for when a mount point you expected does not appear in the default table.
Reading the output
Sample output
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/block/dm-9 111222333 98765432 12345678 89% /dataThe header line *is* the unit declaration, and it is the only place the unit appears — so read the columns through it rather than by position. `1K-blocks` means 1024 bytes each, `512-blocks` means 512, `Size` means the value was humanised, and `Inodes` means the numbers are not bytes at all.
Output fields
| Field | Meaning |
|---|---|
| 1K-blocks | Total size in 1024-byte blocks. `-k` and the default. |
| 512-blocks | Total size in 512-byte blocks. What `-P` produces. |
| Size / Avail | Humanised values, from `-h` or `-H`. Three significant digits. |
| Use% / Capacity | The percentage used. The label depends on the flags. |
| Mounted on | The mount point. Two words in the header, one column in the rows. |
| - | A filesystem that could not be measured. Not zero. |
| IFree / IUse% | The inode columns `-i` substitutes for `Available` and `Use%`. A partition can be full on inodes while it still has bytes going spare, and only these two columns show it. |
| Filesystem | The backing device, or the source for a bind or pseudo mount. On a modern phone this is usually a device-mapper name like `/dev/block/dm-9` rather than a partition you would recognise by sight. |
What access it needs
Read-only and unprivileged: no root, no `adb root`, nothing to enable first. `df` reads the mount table and asks the kernel for each filesystem's block counts, so the numbers describe the filesystem itself rather than anything stored inside it, and no directory has to be readable for a row to be right. That distinction is worth holding on to, because `du` on the same phone will refuse half of what it walks: a `/data` row from `df` is trustworthy even while `du /data` is a wall of `Permission denied`. Passing a path changes only which rows get printed — the argument is examined to find which device it lives on, and an argument the shell cannot examine is reported and skipped rather than guessed at. There is no write form here at all. Freeing space is `pm trim-caches` or a deletion, each with its own page and its own confirmation, and neither of them is reachable by mistyping a flag on this one. The Android Storage Analyzer takes its `/data` figure from this command for the same reason it is on this page: it is the one storage number on the phone that does not depend on what the shell happens to be allowed to open.
Failure messages, decoded
| Message | Meaning |
|---|---|
| df: '/mnt/media_rw/0000-1111': No such file or directory | That path argument could not be examined, so no row is printed for it while the other arguments still are. Checked against `toys/posix/df.c` on the `android11-release` through `android15-release` branches, the path really is wrapped in single quotes here — which is the reliable way to tell this line apart from a table row that happens to contain similar words, since a real row never quotes anything. |
| df: '/data/data/com.example': Permission denied | A path argument has to be stat'ed before `df` can work out which filesystem it sits on, and app-private storage refuses that to the shell. This is the one way a `df` question fails for a permission reason even though the block counts themselves need none: that argument gets no row, the other arguments still do. Ask about the mount point instead — `df /data` answers the same question and needs nothing. |
| df: Unknown option 'z' (see "df --help") | Toybox does not know that letter, and nothing was measured. What it quotes is whatever remained of the argument after the dash at the moment it gave up, so `-kz` is reported as `z` rather than as the whole word — read it as "the first letter I could not place", not as the argument you typed. |
Version and vendor notes
- `-h` and `-H` are indistinguishable in the output: both print the same column labels and the same unit letters, and only the kilobyte suffix reveals its case. A humanised reading cannot tell you which base produced it, so ask for blocks when it matters.
- The shell merges standard error into the output, so a line like `df: /mnt/media_rw/0000-1111: No such file or directory` arrives in the middle of the table and has enough words in it to look like a row. A real row has numbers where the header promised numbers.
- On Android 5.1 and earlier `df` is a different implementation with a different header and no separate mount-point column, and it does not understand `-k` — it treats the flag as a path.
- One flag's grouping genuinely changed between releases: `-k` sat inside the `[-HPkh]` group up to the toybox in Android 11 and left it in Android 12. Note what that kind of group does — toybox switches the earlier flag back off rather than refusing anything — so on the older build `df -P -k` silently drops `-P` and prints a plain 1024-byte-block table, and from Android 12 both flags apply. Neither build says a word about it, which is why a script that spans the boundary should send `-k` on its own.
- Reading the checked source, the unmeasurable-path line quotes the path in single quotes. Nothing here needs root, and `adb root` would not add a single row: the mount table is world-readable and asking a mount point for its block counts does not require the right to walk inside it.
We have a UI for this
Android Storage Analyzer runs this command over USB and parses what comes back — a Chromium browser, no SDK, nothing uploaded.
Related commands
Commands that turn up in the same session as df.
| Command | What it does |
|---|---|
| du | Reports how much disk space a directory tree occupies. |
| dumpsys diskstats | Free space per partition, a disk write latency check, and a cached per-app breakdown of what is using storage. |
| pm trim-caches | Asks the system to drop cached files until the given amount of free space exists. |
More Files and storage commands
Checked against AOSP, toybox and kernel sources while writing the parsers behind our Web ADB tools. Where a behaviour genuinely varies by Android version or manufacturer, this page says so instead of giving a number that would be wrong on half the phones out there.