Last active
October 10, 2021 00:15
-
-
Save d3-X-t3r/901063759fe2525703ae34405a5ac417 to your computer and use it in GitHub Desktop.
[PowerShell] Get File Size on Disk
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Retrieves the size of a file on disk | |
# | |
# Adapted from Kim Doan's original script here: | |
# https://kimconnect.com/powershell-get-size-on-disk-of-files-in-windows/ | |
# | |
# Note: This assumes that the filesystem type is NTFS | |
# and that the cluster size is 4KB | |
[cmdletbinding()] | |
param( | |
[parameter(ValueFromPipeline)] | |
[ValidateNotNullOrEmpty()] | |
[string]$file, | |
[int32]$clusterSize=4096, | |
$maximumSizeThreshold=604 | |
) | |
add-type -type @' | |
using System; | |
using System.Runtime.InteropServices; | |
using System.ComponentModel; | |
using System.IO; | |
namespace Win32Storage | |
{ | |
public class ExtendedFileInfo | |
{ | |
public static long GetFileSizeOnDisk(string file) | |
{ | |
FileInfo info = new FileInfo(file); | |
uint dummy, sectorsPerCluster, bytesPerSector; | |
int result = GetDiskFreeSpaceW(info.Directory.Root.FullName, out sectorsPerCluster, out bytesPerSector, out dummy, out dummy); | |
if (result == 0) throw new Win32Exception(); | |
uint clusterSize = sectorsPerCluster * bytesPerSector; | |
uint hosize; | |
uint losize = GetCompressedFileSizeW(file, out hosize); | |
long size; | |
size = (long)hosize << 32 | losize; | |
return size; | |
} | |
[DllImport("kernel32.dll")] | |
static extern uint GetCompressedFileSizeW([In, MarshalAs(UnmanagedType.LPWStr)] string lpFileName, | |
[Out, MarshalAs(UnmanagedType.U4)] out uint lpFileSizeHigh); | |
[DllImport("kernel32.dll", SetLastError = true, PreserveSig = true)] | |
static extern int GetDiskFreeSpaceW([In, MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName, | |
out uint lpSectorsPerCluster, out uint lpBytesPerSector, out uint lpNumberOfFreeClusters, | |
out uint lpTotalNumberOfClusters); | |
} | |
} | |
'@ | |
function Get-FileSizeOnDisk{ | |
param( | |
[parameter(ValueFromPipeline)] | |
[ValidateNotNullOrEmpty()] | |
[string]$file, | |
[int32]$clusterSize=4096, | |
$maximumSizeThreshold=604 | |
) | |
# At this time, it's unclear as to what minimum size a file should be so that Windows would compact it into NTFS MFT record, | |
# so that there's no wastage of 1 cluster extent; | |
# The range of values seem to be from 539 to 604 bytes | |
[int]$minimumSizeThreshold=539 | |
#[Double]$size=$(try{get-item "$file"}catch{}).Length | |
[Double]$size=[Win32Storage.ExtendedFileInfo]::GetFileSizeOnDisk($file) | |
[int]$sizeOnDisk=0; | |
if ($size -le $minimumSizeThreshold){ | |
$sizeOnDisk=0; | |
}else{ | |
if ($size -lt $maximumSizeThreshold){ | |
$sizeOnDisk=(($size-$minimumSizeThreshold)/($maximumSizeThreshold-$minimumSizeThreshold))*$clusterSize | |
} # This is a blind guess probability that file on disk is equal to cluster size | |
else{ | |
[int]$remainder=$size%$clusterSize | |
if ($remainder -eq 0){ | |
$sizeOnDisk=$size | |
}else{ | |
$sizeOnDisk=$size-$remainder+$clusterSize; | |
} | |
} | |
} | |
#if($size -ge 538 -and $size -lt 542){write-host $file} | |
return $sizeOnDisk | |
} | |
Get-FileSizeOnDisk -file $file -clusterSize $clusterSize -maximumSizeThreshold $maximumSizeThreshold |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment