Chapters/scripting-at-scale/getfoldersize.ps1


Function Get-FolderSize {
[cmdletbinding()]
Param(
[Parameter(Position = 0,ValueFromPipeline,ValueFromPipelineByPropertyName)]
[ValidateNotNullorEmpty()]
[string]$Path = $env:temp
)

Begin {
    Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)"  
} #begin

Process {
    Write-Verbose "[PROCESS] Analyzing: $path"
    
    #define hash table of parameter values for Write-Progress
    $progParam=@{
        Activity = $MyInvocation.MyCommand
        Status = "Querying top level folders"
        CurrentOperation = $path
        PercentComplete = 0
    }

    Write-Progress @progParam

    Write-Verbose "[PROCESS] Get top level folders"
    $top = Get-ChildItem -Path $path -Directory

    #sleeping enough to see the first part of Write-Progress
    Start-Sleep -Milliseconds 300

    #initialize a counter
    $i=0

    #get the number of files and their total size for each
    #top level folder
    foreach ($folder in $top) {
 
     #calculate percentage complete
     $i++
     [int]$pct = ($i/$top.count)*100
 
     #update the param hashtable
     $progParam.CurrentOperation = "Measuring folder size: $($folder.Name)"
     $progParam.Status = "Analyzing"
     $progParam.PercentComplete = $pct

     Write-Progress @progParam

     Write-Verbose "[PROCESS] Calculating folder statistics for $($folder.name)."
     $stats = Get-ChildItem -path $folder.fullname -Recurse -File | 
     Measure-Object -Property Length -Sum -Average

     if ($stats.count) {
        $fileCount = $stats.count
        $size = $stats.sum
     }
     else {
        $fileCount = 0
        $size = 0
     }
     #write a custom object result to the pipeline
     [pscustomobject]@{
       Path = $folder.fullName
       Modified = $folder.LastWriteTime
       Files = $fileCount
       Size = $Size
       SizeKB = [math]::Round($size/1KB,2)
       SizeMB = [math]::Round($size/1MB,2)
       Avg = [math]::Round($stats.average,2)
     } 
    } #foreach

} #process

End {
    Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)"
} #end
}