df

Report free space, per filesystem

Updated 2026-08-31

df reports free space per filesystem, and du adds up the size of files. That is the whole difference between them, and it is why they disagree: df asks the kernel, and du walks a tree and can only count what it is allowed to see.

Give it a path and it answers about whatever filesystem that path is on, so df -h . is usually the fastest way to find out whether the thing you are about to write will fit. Give it nothing and it lists every mounted filesystem, most of which on a modern Debian system are tmpfs pseudo-filesystems that hold no files you put there.

Two ways a disk fills up

Space is one. The other is the inode table, which holds one entry per file and is fixed when the filesystem is created. Exhaust it and writes fail with No space left on device while df -h still reports gigabytes free. Only df -i shows it, and it is a cheaper thing to learn before you need it than during.

Sample files used on this page

Every example below was run against these files. Recreate them to follow along.

two filesystems with sizes this page chose the setup script mounts two tmpfs filesystems with a fixed size and a fixed inode count, so every figure below is one it set rather than a property of the machine running it. /srv/backups holds a single 40M file called site-backup.tar; /srv/small is empty and has 32 inodes, few enough to run out of in one example.

Type   Size Inodes Mounted on
tmpfs  100M   4.9K /srv/backups
tmpfs   10M     32 /srv/small
24 outputs, collapsed by default

Reading the output

df takes a path and answers about the filesystem that path is on. Without one it reports every mounted filesystem, which on a real machine is a long list.

List every mounted filesystem

df -h

What most people type, and the one form this page cannot show you: the list is whatever your machine has mounted, at whatever size, and half of it is pseudo-filesystems the kernel keeps for itself. Every other example here names a path, and naming one is the better habit anyway.

Ask how much room is left

df -h /srv/backups

-h prints sizes people can read. Six columns: the device, its total size, how much is used, how much is available, that as a percentage, and where it is mounted.

Show output
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           100M   40M   60M  40% /srv/backups

See what it prints without -h

df /srv/backups

Blocks of 1024 bytes, the default, and almost never what you want at a prompt. In a script it is: the numbers compare directly, with no unit to strip off the end first.

Show output
Filesystem     1K-blocks  Used Available Use% Mounted on
tmpfs             102400 40960     61440  40% /srv/backups

Ask about the directory you are in

cd /srv/backups; df -h .

The shortest useful form. Before unpacking an archive or starting a build, this is the check that takes a second.

Show output
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           100M   40M   60M  40% /srv/backups

Ask about several at once

df -h /srv/backups /srv/small

The paths are reported in the order given, a row each. Put two paths on the same filesystem and you get a single row, because df reports filesystems and not paths.

Show output
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           100M   40M   60M  40% /srv/backups
tmpfs            10M     0   10M   0% /srv/small

Point it at a file rather than a directory

df -h /srv/backups/site-backup.tar

The answer is about the filesystem holding the file, not the file. df never reports on a file's own size, and asking it to is the usual reason somebody ends up wanting du instead.

Show output
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           100M   40M   60M  40% /srv/backups

Show what kind of filesystem it is

df -T /srv/backups

-T inserts a Type column. Useful when you are trying to work out whether the thing you are looking at is a real disk or one of the pseudo-filesystems the kernel mounts for itself.

Show output
Filesystem     Type  1K-blocks  Used Available Use% Mounted on
tmpfs          tmpfs    102400 40960     61440  40% /srv/backups

Add up several filesystems

df -h --total /srv/backups /srv/small

--total appends a summary row. The Mounted on column is a dash there, because a total is not mounted anywhere.

Show output
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           100M   40M   60M  40% /srv/backups
tmpfs            10M     0   10M   0% /srv/small
total           110M   40M   70M  37% -

Find which mount point holds a file

df --output=target /srv/backups/site-backup.tar

--output=target narrows the report to the mount point alone. Handy when a path runs through several symlinks and you want to know where it really lands.

Show output
Mounted on
/srv/backups

Choosing the columns and the units

Pick the columns you want

df --output=source,fstype,size,pcent,target -h /srv/backups

--output replaces the default set with the fields you name, in the order you name them. The field names are not the column headings: source is the device, target is the mount point, and pcent is Use%.

Show output
Filesystem     Type   Size Use% Mounted on
tmpfs          tmpfs  100M  40% /srv/backups

Cut it down to the two figures you care about

df --output=target,avail -h /srv/backups /srv/small

Where it is and how much is left. Narrow output like this is easier to read at a glance and easier to feed to something else than the full six columns.

Show output
Mounted on   Avail
/srv/backups   60M
/srv/small     10M

Report in megabytes

df -B M /srv/backups

-B sets the block size, so the numbers are all in one unit rather than each in whichever unit fits. That makes a column of them comparable, where -h gives you 900M next to 1.1G and leaves the arithmetic to you.

Show output
Filesystem     1M-blocks  Used Available Use% Mounted on
tmpfs               100M   40M       60M  40% /srv/backups

Ask for kilobytes explicitly

df -k /srv/backups

-k is -B K and matches the default on Debian. Worth writing out in a script, because the default is a setting and POSIXLY_CORRECT changes it to 512-byte blocks.

Show output
Filesystem     1K-blocks  Used Available Use% Mounted on
tmpfs             102400 40960     61440  40% /srv/backups

Use the portable output format

df -P /srv/backups

-P is the POSIX output format, and its guarantee is one line per filesystem however long the device name is. POSIX specifies 512-byte blocks for it; GNU df keeps 1024 unless POSIXLY_CORRECT is set, so the heading names the size rather than leaving you to assume one.

Show output
Filesystem     1024-blocks  Used Available Capacity Mounted on
tmpfs               102400 40960     61440      40% /srv/backups

Report in powers of 1000

df --si /srv/backups

--si divides by 1000 where -h divides by 1024, so the same filesystem reads 105M rather than 100M. Disk manufacturers use the first convention and the kernel uses the second, and this flag is where that argument shows up on your own machine.

Show output
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           105M   42M   63M  40% /srv/backups

Show only the size columns

df -h --output=size,used,avail /srv/backups

No device and no mount point. Worth knowing that --output drops the columns you leave out rather than hiding them, so the widths change with the fields you ask for.

Show output
 Size  Used Avail
 100M   40M   60M

Ask the same question about inodes

df --output=itotal,iused,iavail,ipcent /srv/small

The inode fields have their own names, all beginning with i. Mixing them with the block fields in one --output works and gives you a wide row that answers both questions at once.

Show output
Inodes IUsed IFree IUse%
    32     1    31    4%

Test whether two paths are on one filesystem

df --output=source /srv/backups /srv/backups/site-backup.tar | sort -u

sort -u leaves the heading and a single device, so both paths are on the same filesystem. A second device would mean a mv between them is a copy and a delete rather than a rename, so one is instant and the other takes as long as the file is big.

Show output
Filesystem
tmpfs

Get a bare number for a script

df --output=avail -B M /srv/backups | tail -1 | tr -d ' M'

--output with one field, tail -1 to drop the heading, and tr to strip the unit and the padding. Fix the unit with -B or the comparison is against text: -h gives you 60M one day and 1.2G the next.

Show output
60

Get the percentage the same way

df --output=pcent /srv/backups | tail -1 | tr -d ' %'

The form a monitoring script wants, and it needs no -B, since a percentage carries no unit to vary. Compare it as a number and alert above whatever threshold you can actually act on.

Show output
40

Space free, and still no space left

A filesystem has two things it can run out of. Every figure below comes from /srv/small, which has 10M of space and room for 32 files.

Count the inodes instead of the bytes

df -i /srv/small

-i reports the inode table rather than the blocks. One entry is already used, for the mount point's own directory.

Show output
Filesystem     Inodes IUsed IFree IUse% Mounted on
tmpfs              32     1    31    4% /srv/small

Fill the table up

cd /srv/small
for i in $(seq 1 40); do touch "file$i" 2>/dev/null; done
ls | wc -l

Forty attempts and thirty-one files, because the directory itself holds the thirty-second inode. The failures were silent here only because the loop discards them.

Show output
31

Watch a write fail on a filesystem with space free

cd /srv/small
for i in $(seq 1 40); do touch "file$i" 2>/dev/null; done
touch one-more.txt

No space left on device, on a filesystem that has used none of its 10M. The message is the same one you get for a genuinely full disk, and it is the reason this failure wastes so much time: everything you check first says there is room.

Show output
touch: cannot touch 'one-more.txt': No space left on device

Ask both questions and see them disagree

cd /srv/small
for i in $(seq 1 40); do touch "file$i" 2>/dev/null; done
df -h . | tail -1
df -i . | tail -1

Nought per cent of the space and a hundred per cent of the inodes. Run df -i before anything else when a write fails and df -h looks healthy: it is one command and it either explains the problem or rules it out.

Show output
tmpfs            10M     0   10M   0% /srv/small
tmpfs              32    32     0  100% /srv/small

See df and du disagree about the same filesystem

dd if=/dev/zero of=/srv/small/tmpfile bs=1M count=5 status=none
exec 3< /srv/small/tmpfile
rm /srv/small/tmpfile
du -sh /srv/small
df -h /srv/small | tail -1

A deleted file that a process still has open. du walks the directory and finds nothing, because the name is gone; df asks the kernel, which cannot release the blocks until the last descriptor closes. On a real machine this is usually a log file somebody deleted without restarting the service that writes it.

Show output
0	/srv/small
tmpfs            10M  5.0M  5.0M  50% /srv/small