Size on disk of file

hello all.
I would like to know how to get the size on disk of a file.
I attach a photo indicating what I need. for example:

thanks in advance.

I think to do this you need to know the allocation size of the volume, then adjust the number up to the next allocation size.

allocation_size * ((file_size mod allocation_size) + 1)

Interesting question @secasados. According to this blog from 2016 How does Explorer calculate "Size on disk"? - The Old New Thing, this value is affected by a number of factors:

The algorithm for “Size on disk” is as follows:
o If the file is sparse, then report the number of non-sparse bytes.
o If the file is compressed, then report the compressed size. The compressed size may be less than a full sector.
o If the file is neither sparse nor compressed, then report the nominal file size, rounded up to the nearest cluster.

It would be quite challenging to create relevance to calculate that directly but looking around the 'net there are a few hits where this has been done (with varying success) using Powershell or by various scripts. e.g. c# - Get size of file on disk - Stack Overflow
Not a solution but sowhere to start perhaps…

1 Like

I remember this topic coming up in a user group back in 2017 or 2018. There were over 25 “really smart people” in the room talking BigFix things. We came to the conclusion that there were not really any good ways to do this accurately, for some of the same reasons mentioned in the MS article above.

That said, Here is a layout of how you might get there in Relevance Language, at least for an NTFS partition.
I have a file named DLV cscript command.txt in my test folder. it has a size of 59 bytes and a size on disk of 4096 bytes (4k)

Get Real Size

q: (name of it, (it as uppercase &"\") of name of drive of it, size of it) of file "DLV cscript command.txt" of folder "c:\test"
A: DLV cscript command.txt, C:\, 59

Get Cluster Size of all disks using a WMI query, which does carry some expense.

q: (string value of property "name" of it, integer value of property "blocksize" of it) whose (item 0 of it contains ":\") of select objects "name, blocksize from win32_Volume" of wmi
A: E:\, 4096
A: C:\, 4096
A: D:\, 4096

put the outputs together (as tuple string sets) and figure out which drive my file is on, so I know the cluster size to divide then multiply by.

First flatten things into String Sets

q: set of (it as string) of ((string value of property "name" of it, integer value of property "blocksize" of it) whose (item 0 of it contains ":\") of select objects "name, blocksize from win32_Volume" of wmi), set of (it as string) of ((name of it, (it as uppercase &"\") of name of drive of it, size of it) of file "DLV cscript command.txt" of folder "c:\test") 
E: This expression evaluates to an unrepresentable object of type "( string set, string set )"

then put all elements together

q: (elements of item 0 of it, elements of item 1 of it) of (set of (it as string) of ((string value of property "name" of it, integer value of property "blocksize" of it) whose (item 0 of it contains ":\") of select objects "name, blocksize from win32_Volume" of wmi), set of (it as string) of ((name of it, (it as uppercase &"\") of name of drive of it, size of it) of file "DLV cscript command.txt" of folder "c:\test"))
A: ( C:\, 4096 ), ( DLV cscript command.txt, C:\, 59 )
A: ( D:\, 4096 ), ( DLV cscript command.txt, C:\, 59 )
A: ( E:\, 4096 ), ( DLV cscript command.txt, C:\, 59 )

Then filter for the matches with a Whose

q: (elements of item 0 of it, elements of item 1 of it) whose (tuple string item 0 of item 0 of it = tuple string item 1 of item 1 of it) of (set of (it as string) of ((string value of property "name" of it, integer value of property "blocksize" of it) whose (item 0 of it contains ":\") of select objects "name, blocksize from win32_Volume" of wmi), set of (it as string) of ((name of it, (it as uppercase &"\") of name of drive of it, size of it) of file "DLV cscript command.txt" of folder "c:\test"))
A: ( C:\, 4096 ), ( DLV cscript command.txt, C:\, 59 )

Now that we have the file size and cluster size. First I will make sure the appropriate strings are converted into integers and flatten out the tuple into a single layer.

q: (tuple string item 0 of item 1 of it, tuple string item 1 of item 0 of it, tuple string items 2 of items 1 of it) of (elements of item 0 of it, elements of item 1 of it) whose (tuple string item 0 of item 0 of it = tuple string item 1 of item 1 of it) of (set of (it as string) of ((string value of property "name" of it, integer value of property "blocksize" of it) whose (item 0 of it contains ":\") of select objects "name, blocksize from win32_Volume" of wmi), set of (it as string) of ((name of it, (it as uppercase &"\") of name of drive of it, size of it) of file "DLV cscript command.txt" of folder "c:\test"))
A: DLV cscript command.txt, 4096, 59

Then we can Math It to round up to nearest cluster size.

q: (item 0 of it, item 2 of it, (item 2 of it / item 1 of it + 1) * item 1 of it) of (tuple string item 0 of item 1 of it, tuple string item 1 of item 0 of it as integer, tuple string items 2 of items 1 of it as integer) of (elements of item 0 of it, elements of item 1 of it) whose (tuple string item 0 of item 0 of it = tuple string item 1 of item 1 of it) of (set of (it as string) of ((string value of property "name" of it, integer value of property "blocksize" of it) whose (item 0 of it contains ":\") of select objects "name, blocksize from win32_Volume" of wmi), set of (it as string) of ((name of it, (it as uppercase &"\") of name of drive of it, size of it) of file "DLV cscript command.txt" of folder "c:\test"))
A: DLV cscript command.txt, 59, 4096

Now that we have a solve for a single file, we could even expand it to pull all the files in a folder, because I have my WMI call in a set at the bottom of the tuple, we do not pay that price more than once.

Also I noticed 0 size files were showing up as having space on disk, so I added in an If statement to catch 0 size files (which are also 0 on disk)

q: (item 0 of it, item 2 of it, (if item 2 of it = 0 then 0 else (item 2 of it / item 1 of it + 1) * item 1 of it)) of (tuple string item 0 of item 1 of it, tuple string item 1 of item 0 of it as integer, tuple string items 2 of items 1 of it as integer) of (elements of item 0 of it, elements of item 1 of it) whose (tuple string item 0 of item 0 of it = tuple string item 1 of item 1 of it) of (set of (it as string) of ((string value of property "name" of it, integer value of property "blocksize" of it) whose (item 0 of it contains ":\") of select objects "name, blocksize from win32_Volume" of wmi), set of (it as string) of ((name of it, (it as uppercase &"\") of name of drive of it, size of it) of files  of folder "c:\test"))
A: Abc_20210115612456.txt, 0, 0
A: Abc_20210120342156.txt, 0, 0
A: Abc_20210121225468.txt, 0, 0
A: Abc_20210123165009.txt, 0, 0
A: Abc_20210124184449.txt, 0, 0
A: Abc_20210125205107.txt, 0, 0
A: Abc_20210126224733.txt, 0, 0
A: DLV cscript command.txt, 59, 4096
A: DLV parse for Win 7.qna, 1645, 4096
A: Fake.txt, 0, 0
A: Group.txt, 133, 4096
A: Install Multiple Activation Key.url, 218, 4096
A: LicenseStatus Values.url, 188, 4096
A: Screenshot mapping WMI entries to SLMGR DLV entries.png, 99327, 102400
A: WMI style DLV answer v2.qna, 3043, 4096
A: WMI style DLV answer v3.qna, 463, 4096
A: WMI style DLV answer.qna, 691, 4096
A: dlv.txt, 818, 4096
A: one more file 5.txt, 0, 0
A: patchesforubuntu1804.txt, 18833, 20480
A: slmgr into file.url, 211, 4096
A: test.txt, 262, 4096
A: test1_20210123165009.txt, 0, 0
A: test2_20210124184449.txt, 0, 0
A: test3_20210125205107.txt, 0, 0
A: test4_20210126224733.txt, 0, 0
T: 18.798 ms

Kind of expensive for an extra 4k worth of resolution on file size.

2 Likes

(and don’t get started on “is file and folder compression turned on”, or hardlinks, or …)

One last update for Windows… With the old formula if the size is a perfect multiple of cluster size, I was overcounting by one cluster. This mod check will fix it and handle the 0 size edge at the same time

q: (item 0 of it, item 2 of it, (if item 2 of it mod item 1 of it = 0 then item 2 of it else (((item 2 of it / item 1 of it) +1)* item 1 of it ))) of (tuple string item 0 of item 1 of it, tuple string item 1 of item 0 of it as integer, tuple string items 2 of items 1 of it as integer) of (elements of item 0 of it, elements of item 1 of it) whose (tuple string item 0 of item 0 of it = tuple string item 1 of item 1 of it) of (set of (it as string) of ((string value of property "name" of it, integer value of property "blocksize" of it) whose (item 0 of it contains ":\") of select objects "name, blocksize from win32_Volume" of wmi), set of (it as string) of ((name of it, (it as uppercase &"\") of name of drive of it, size of it) of files  of folder "c:\test"))
A: Abc_20210115612456.txt, 0, 0
A: Abc_20210120342156.txt, 0, 0
A: Abc_20210121225468.txt, 0, 0
A: Abc_20210123165009.txt, 0, 0
A: Abc_20210124184449.txt, 0, 0
A: Abc_20210125205107.txt, 0, 0
A: Abc_20210126224733.txt, 0, 0
A: DLV cscript command.txt, 59, 4096
A: DLV parse for Win 7.qna, 1645, 4096
A: Fake.txt, 0, 0
A: Group.txt, 133, 4096
A: Install Multiple Activation Key.url, 218, 4096
A: LicenseStatus Values.url, 188, 4096
A: Screenshot mapping WMI entries to SLMGR DLV entries.png, 99327, 102400
A: WMI style DLV answer v2.qna, 3043, 4096
A: WMI style DLV answer v3.qna, 463, 4096
A: WMI style DLV answer.qna, 691, 4096
A: dlv.txt, 818, 4096
A: one more file 5.txt, 0, 0
A: patchesforubuntu1804.txt, 18833, 20480
A: slmgr into file.url, 211, 4096
A: test.txt, 262, 4096
A: test1_20210123165009.txt, 0, 0
A: test2_20210124184449.txt, 0, 0
A: test3_20210125205107.txt, 0, 0
A: test4_20210126224733.txt, 0, 0
2 Likes