PowerShell to get Size on Disk of files

Source:www.opentechguides.com | Date Published: 2017-02-10 15:57:56

If you right click a file or folder in windows and look at it properties you will find there are two size properties - Size and Size on Disk. Size is the actual size of the file in bytes and Size on disk is the disk space required to store that file. The two sizes can be the same in some cases or it could be hugely different especially if its a sparse file or if its a compressed file that is stored in a volume that supports compression.

To get the size of a file in PowerShell you just have to run the Get-Item command

PS C:\Users\> Get-Item export.sql

    Directory: C:\Users

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        23/01/2017     15:25     177331 export.sql

There isn't any single command or cmdlets that gives you the size on disk of a file, however we could achieve this with .Net Platform Invoke (P/Invoke) feature and the PowerShell Add-Type cmdlet.

First you create a .NET class that finds the actual size on disk of a file. Inside this class you will use the Win32 function GetCompressedFileSizeW to which returns the size in bytes used to store a file.

The Add-Type cmdlet is used to add the class to your PowerShell session. Finally get each file from the specfied directory and call the function in .Net class you created with full file name as paramater.

Here is the full script:

Script: Get-FileSizeOnDisk.ps1


  Powershell script to get file size and size on disk of all files
  in a directory.
  This PowerShell script gets file size and size on disk in bytes
  of all files in a directory.
   Directory path of the files to check. If this parameter is not
   specified the default value is current directory.
  Version:        1.0
  Author:         Open Tech Guides
  Creation Date:  06-Feb-2017
  Get-FileSizeOnDisk c:\myfolder


param (

$source = @"
 using System;
 using System.Runtime.InteropServices;
 using System.ComponentModel;
 using System.IO;

 namespace Win32
    public class Disk {
    static extern uint GetCompressedFileSizeW([In, MarshalAs(UnmanagedType.LPWStr)] string lpFileName,
    [Out, MarshalAs(UnmanagedType.U4)] out uint lpFileSizeHigh);	
    public static ulong GetSizeOnDisk(string filename)
      uint HighOrderSize;
      uint LowOrderSize;
      ulong size;

      FileInfo file = new FileInfo(filename);
      LowOrderSize = GetCompressedFileSizeW(file.FullName, out HighOrderSize);

      if (HighOrderSize == 0 && LowOrderSize == 0xffffffff)
	 throw new Win32Exception(Marshal.GetLastWin32Error());
      else { 
	 size = ((ulong)HighOrderSize << 32) + LowOrderSize;
	 return size;


Add-Type -TypeDefinition $source

$result = @()

Get-ChildItem $path | Where-Object { ! $_.PSIsContainer} | Foreach-Object { 
    $size = [Win32.Disk]::GetSizeOnDisk($_.FullName)
    $obj = New-Object PSObject
    Add-Member -InputObject $obj -MemberType NoteProperty -Name "File Name" -Value $_.Name
    Add-Member -InputObject $obj -MemberType NoteProperty -Name "Size" -Value $_.Length
    Add-Member -InputObject $obj -MemberType NoteProperty -Name "Size on Disk" -Value $size
    $result += $obj

write-output $result 

Sample output

PS C:\> Get-FileSizeOnDisk.ps1 C:\Users

File Name          Size        Size on Disk
---------          ----        ------------
export.sql       177331               45056

PS C:\>

Open Tech Guides | www.opentechguides.com