Mark Allison
Mark Allison

Reputation: 7228

Get free space of a supplied drive path in powershell

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:

So I want to do something like:

function Get-FreeSpace {
    param (
        $path
    );  

    # 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:

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.

Upvotes: 4

Views: 5693

Answers (2)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200273

Try this:

function Get-FreeSpace {
    Param(
        $path
    );

    if ($path[-1] -ne '\') { $path += '\' }
    $filter = "DriveType=3 And Name='$($path -replace '\\', '\\')'"
    $free = Get-WmiObject Win32_Volume -Filter $filter |
            Select-Object -Expand 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.

Update:

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

function Get-FreeSpace {
    Param(
        $path
    );

    $free = Get-WmiObject Win32_Volume -Filter "DriveType=3" |
            Where-Object { $path -like "$($_.Name)*" } |
            Sort-Object Name -Desc |
            Select-Object -First 1 FreeSpace |
            ForEach-Object { $_.FreeSpace / (1024*1024) }
    return ([int]$free)
}

The Where-Object clause selects all mount points with a partial path matching $path, and the subsequent Sort-Object | Select-Object selects the one with the longest match.

Upvotes: 4

lyngvi
lyngvi

Reputation: 1362

A simpler variant:

function Get-FreeSpace {
    param ([string]$path);
    $space = (Get-Volume -FilePath $path).SizeRemaining;
    return [int64]($space / (1024 * 1024)); # this would otherwise be a float
}

Get-Volume -FilePath retrieves the volume associated with the provided path; from that volume, we extract SizeRemaining and divide out 1MB. The cast to int64 is because the operation would otherwise return float.

Upvotes: 3

Related Questions