13

I'm creating sparse files in python as follows:

>>> f = open('testfile', 'ab')
>>> f.truncate(1024000)
>>> f.close()

when the file is done, it takes up 0 disk space, but its inode size is set to my truncated value (1000K):

igor47@piglet:~/test$ ls -lh testfile 
-rw-r--r-- 1 igor47 igor47 1000K 2010-07-09 04:02 testfile
igor47@piglet:~/test$ du -hs testfile 
0   testfile

How do I get the file's real space usage (allocated size) inside python? The stat call returns the file's apparent size, and I have no idea how else to get the real usage other than to read the entire file (it may become quite large)

>>> os.stat('testfile').st_size
1024000
Muschel
  • 340
  • 5
  • 11
Igor Serebryany
  • 3,307
  • 3
  • 29
  • 41
  • 1
    on a side note, if you are copying sparse files using python's shutil module, this will not work, as shutil doesn't support sparse files. – Igor Serebryany Jul 13 '10 at 20:35

1 Answers1

18
>>> os.stat('testfile').st_blocks*512
0

Tadaa :)

st_blocks is the number of 512-byte blocks actually allocated to the file. Note that st_blocks is not guaranteed to be present in all operating systems, but those that support sparse files generally do.

wump
  • 4,277
  • 24
  • 25
  • 4
    `st_blksize` provides actual block size of the filesystem. Generally speaking it doesn't have to be 512 bytes. – SilentGhost Jul 09 '10 at 11:33
  • 7
    I was confused for a moment, but that's not true. `st_blksize` is the "preferred" file system block size. `st_blocks` is guaranteed to be in blocks of 512 bytes (see the manpage). – wump Jul 09 '10 at 12:49
  • This particular solution was working this morning, but after i've changed the server machine it suddenly stopped working. Do you have any advice on that? – Hgeg Oct 08 '12 at 00:42
  • this return different value than `du -b` So I think this is wrong – Wang Mar 31 '22 at 16:57
  • @Wang no: du -b shows the sparse file size, like ls -l do. du -s and ls -ls shows the real allocated space ( ls -ls shows this in the first column) – benba May 18 '22 at 08:36