Alex
Alex

Reputation: 843

Get actual disk space of a file

How do I get the actual filesize on disk in python? (the actual size it takes on the harddrive).

Upvotes: 19

Views: 31297

Answers (7)

J_K
J_K

Reputation: 71

Practically 12 years and no answer on how to do this in windows...

Here's how to find the 'Size on disk' in windows via ctypes;

import ctypes
def GetSizeOnDisk(path):
    '''https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getcompressedfilesizew'''
    filesizehigh = ctypes.c_ulonglong(0) # not sure about this... something about files >4gb
    return ctypes.windll.kernel32.GetCompressedFileSizeW(ctypes.c_wchar_p(path),ctypes.pointer(filesizehigh))

'''
>>> os.stat(somecompressedorofflinefile).st_size
943141
>>> GetSizeOnDisk(somecompressedorofflinefile)
671744
>>>
'''

Upvotes: 4

hft
hft

Reputation: 1245

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

Upvotes: 5

Jonathon Reinhart
Jonathon Reinhart

Reputation: 137398

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 */

Upvotes: 7

Jared Wilber
Jared Wilber

Reputation: 6775

To get the disk usage for a given file/folder, you can do the following:

import os

def disk_usage(path):
    """Return cumulative number of bytes for a given path."""
    # get total usage of current path
    total = os.path.getsize(path)
    # if path is dir, collect children
    if os.path.isdir(path):
        for file_name in os.listdir(path):
            child = os.path.join(path, file_name)
            # recursively get byte use for children
            total += disk_usage(child)
    return total

The function recursively collects byte usage for files nested within a given path, and returns the cumulative use for the entire path. You could also add a print "{path}: {bytes}".format(path, total) in there if you want the information for each file to print.

Upvotes: 0

Giampaolo Rodolà
Giampaolo Rodolà

Reputation: 13056

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

Upvotes: 18

ephemient
ephemient

Reputation: 204668

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

Upvotes: 2

TZHX
TZHX

Reputation: 5377

I'm not certain if this is size on disk, or the logical size:

import os
filename = "/home/tzhx/stuff.wev"
size = os.path.getsize(filename)

If it's not the droid your looking for, you can round it up by dividing by cluster size (as float), then using ceil, then multiplying.

Upvotes: 0

Related Questions