Take the 2-minute tour ×

I am trying to create a Function to return the amount of free drive space in MB. The function takes the path name as a parameter and must cope with mount points. My drives are set up like this:

  • C:\ - Disk0
  • G:\ - Disk1
  • G:\Data - Disk2

So I want to do something like:

function Get-FreeSpace {
    param (

    # iterate through and find the volume, detect if in a mount point and return free space

    return [int]$freeSpace;

I have looked at using this array as a starting point in my function, but I am getting stuck.

$vols = Get-WMIObject Win32_Volume -filter "DriveType=3" -computer $computerName | Select Caption,DriveLetter,Label,@{Name="DiskSize(GB)";Expression={[decimal]("{0:N1}" -f($_.capacity/1gb))}},@{Name="PercentFree(%)";Expression={"{0:P2}" -f(($_.freespace/1mb)/($_.capacity/1mb))}}

$vols is returning a System.Array of PSCustomObject types. So if I pass the function the following paths:

  • G:\Data\My\Test\Path
  • G:\Data

It will find the free space of the G:\Data mount point.

If I pass it G:\Some\Other\Path, it will return the free space of the G:\ drive. I want to use it like so: $freeSpace = Get-FreeSpace "G:\Some\Other\Path"

I would be grateful for any help.

share|improve this question
add comment

1 Answer

up vote 2 down vote accepted

Try this:

function Get-FreeSpace {
  param (

  if ($path[-1] -ne '\') { $path += '\' }
  $filter = "DriveType=3 And Name='$($path -replace '\\', '\\')'"
  $free = (gwmi Win32_Volume -Filter $filter | select FreeSpace).freespace
  return ($free / (1024*1024))

You need to double the backslashes in $path, because they must be escaped for WMI queries. For that (confusing as it may seem) you have to replace '\\' with '\\', because the first occurrence is a regular expression where the backslash must be escaped, whereas the second occurrence is a string literal with a double backslash.


To match a partial path you could use the -Like operator:

function Get-FreeSpace {
  param (

  $free = gwmi Win32_Volume -Filter "DriveType=3" `
    | where { $path -Like "$($_.Name)*" } `
    | sort Name -Desc `
    | select -First 1 FreeSpace `
    | % { $_.freespace / (1024*1024) }
  return ([int]$free)

The where clause selects all mount points with a partial path matching $path, and the subsequent sort | select selects the one with the longest match.

Note: I know that I wouldn't have to escape the line breaks if I put the pipe at the end of the line, but I prefer having the pipe at the beginning of a new line. That way you can immediately see where a pipeline is continued from the previous line.

share|improve this answer
Almost! Thanks for the reply. I need it to work for sub-folders too. Read more closely the last part of my question. If I have a drive with 2GB free space as a mount point of G:\Data and I pass in G:\Data\SubFolder, I get 0 returned, and not the free space of the mount point. Similarly, your function does not work for Sub Folders of the root drive. So, if G:\Log is not a mount point and I pass that to the function, I also get 0. –  Moo MinTroll Nov 7 '12 at 8:46
@MarkAllison See updated answer. –  Ansgar Wiechers Nov 7 '12 at 12:26
add comment

Your Answer


