Skip to content

Instantly share code, notes, and snippets.

@d3-X-t3r
Last active October 10, 2021 00:15
Show Gist options
  • Save d3-X-t3r/901063759fe2525703ae34405a5ac417 to your computer and use it in GitHub Desktop.
Save d3-X-t3r/901063759fe2525703ae34405a5ac417 to your computer and use it in GitHub Desktop.
[PowerShell] Get File Size on Disk
# 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