Get actual disk space of a file

Here is the correct way to get a file's size on disk, on platforms where st_blocks is set:

import os

def size_on_disk(path):
    st = os.stat(path)
    return st.st_blocks * 512

Other answers that indicate to multiply by os.stat(path).st_blksize or os.vfsstat(path).f_bsize are simply incorrect.

The Python documentation for os.stat_result.st_blocks very clearly states:

st_blocks
Number of 512-byte blocks allocated for file. This may be smaller than st_size/512 when the file has holes.

Furthermore, the stat(2) man page says the same thing:

blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */

st = os.stat(…)
du = st.st_blocks * st.st_blksize

UNIX only:

import os
from collections import namedtuple

_ntuple_diskusage = namedtuple('usage', 'total used free')

def disk_usage(path):
    """Return disk usage statistics about the given path.

    Returned valus is a named tuple with attributes 'total', 'used' and
    'free', which are the amount of total, used and free space, in bytes.
    """
    st = os.statvfs(path)
    free = st.f_bavail * st.f_frsize
    total = st.f_blocks * st.f_frsize
    used = (st.f_blocks - st.f_bfree) * st.f_frsize
    return _ntuple_diskusage(total, used, free)

Usage:

>>> disk_usage('/')
usage(total=21378641920, used=7650934784, free=12641718272)
>>>

Edit 1 - also for Windows: https://code.activestate.com/recipes/577972-disk-usage/?in=user-4178764

Edit 2 - this is also available in Python 3.3+: https://docs.python.org/3/library/shutil.html#shutil.disk_usage


Update 2021-03-26: Previously, my answer rounded the logical size of the file up to be an integer multiple of the block size. This approach only works if the file is stored in a continuous sequence of blocks on disk (or if all the blocks are full except for one). Since this is a special case (though common for small files), I have updated my answer to make it more generally correct. However, note that unfortunately the statvfs method and the st_blocks value may not be available on some system (e.g., Windows 10).

Call os.stat(filename).st_blocks to get the number of blocks in the file.

Call os.statvfs(filename).f_bsize to get the filesystem block size.

Then compute the correct size on disk, as follows:

num_blocks = os.stat(filename).st_blocks
block_size = os.statvfs(filename).f_bsize
sizeOnDisk = num_blocks*block_size

Tags:

Python