Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
“Disk full? It was only at 60% last week! Where did all the space go?”
If you haven’t said this, then you probably won’t appreciate this post. It seems such a relatively simple task – give me a list of the biggest folders on the drive. Yes, C:\Windows (or wherever you’ve stashed $env:WinDir to) will be one of them, but we’ll then have to rely on eyeballing and common sense (uh-oh) to address the offenders once we’ve found our disk hogs.
In other words, if you do something like this: Get-FolderSize c:\ | Sort-Object -Descending -Property Size | Select-Object -First 10 | Remove Item
, you deserve what you get.
Humour aside, I run into this situation at least once a week. On my home network, I run WinDirStat, but at work we have certain ‘clean’ labs that don’t allow willy-nilly downloaded apps to run. In those labs, when I get the SCOM alert, I usually go searching for some script to do it. For some reason, I’ve yet to find one that works reliably. (It turns out I wrote one a few days ago, too. Oh, well.)
So I decided to write my own:
function Get-FolderSize
{param ([parameter(valuefrompipeline=$true)][string[]]$Path = @((Get-Location).ProviderPath));
begin
{
########################################
function invoke-worker
{
param ([string]$Path = $null);
# handle bum data
if (!$Path -or !(Test-Path -Path $Path))
{
return;
} # if (!$Path -or !(Test-Path -Path $Path))
$Path = (Resolve-Path -Path $Path).ProviderPath;
Write-Progress $MyInvocation.MyCommand.Name $Path;
[long]$size = 0;
# this is were most of the work occurs
Get-ChildItem -Path $Path |
% {
if ($_.PsIsContainer)
{ # if it's a folder, recurse and return size
$size += invoke-worker -Path $_.FullName;
} # if ($_.PsIsContainer)
else
{ # otherwise, add it's size
$size += $_.Length;
} # if ($_.PsIsContainer) ... else
} # Get-ChildItem -Path $Path |
# we've iterated (and recursed) through the folder. cache for summary view in the end {} block
$script:output += New-Object -TypeName PsObject |
Select-Object -Property @{
n = 'Path';
e = { $Path; }
}, @{
n = 'Size';
e = { $size; }
} # $object = New-Object -TypeName PsObject | Select-Object...
# output folder size
$size;
} # function invoke-worker
########################################
$script:output = @();
} # begin
process
{
foreach ($_path in $Path)
{ # this will return the file size, but we don't care. We want the summary view in the end {} block
invoke-worker -Path $Path | Out-Null;
} # foreach ($_path in $Path)
} # process
end
{ # filter out all the zero-length files
$script:output |
? { $_.size; }
} # end
} # function Get-FolderSize