PowerShell Get-Folder-Size: Calculate Directory Size

PowerShell Get-Folder-Size: Calculate Directory Size

PowerShell Tips Editor 3 min read
PowerShell Get-Folder-Size: Calculate Directory Size

File Explorer shows folder sizes, but only one folder at a time after a slow calculation. PowerShell calculates folder sizes recursively, formats them in GB or MB, and reports the top ten largest subfolders — faster and more actionable than any GUI. This guide shows you how to get folder size in PowerShell using Get-ChildItem and Measure-Object, with patterns for formatted output, subfolder comparisons, handling access errors, and exporting size reports to CSV.

Sum All Files Recursively

The core pattern: recurse all files and sum their Length property with Measure-Object:

# Total size of a folder and all subfolders
$result = Get-ChildItem 'C:\Users\Alice' -Recurse -File -ErrorAction SilentlyContinue |
    Measure-Object -Property Length -Sum

"Total files: $($result.Count)"
"Total bytes: $($result.Sum)"
Total files: 4823
Total bytes: 19327352832

The -ErrorAction SilentlyContinue is essential — it silently skips directories where access is denied (like system folders) and continues the measurement. Without it, the first permission error stops the entire command.

Format as MB and GB

Convert bytes to human-readable units using PowerShell’s built-in multipliers:

$path = 'C:\Users\Alice'

$bytes = (Get-ChildItem $path -Recurse -File -ErrorAction SilentlyContinue |
          Measure-Object -Property Length -Sum).Sum

$sizeKB = [math]::Round($bytes / 1KB, 1)
$sizeMB = [math]::Round($bytes / 1MB, 2)
$sizeGB = [math]::Round($bytes / 1GB, 3)

Write-Output "Folder: $path"
Write-Output "Size:   $sizeGB GB  ($sizeMB MB  |  $sizeKB KB)"
Folder: C:\Users\Alice
Size:   18.006 GB  (18437.45 MB  |  18879832.5 KB)

Report Top 10 Largest Subfolders

The most useful disk space investigation tool — find which subfolders are consuming the most space:

$rootPath = 'C:\'

Get-ChildItem $rootPath -Directory -ErrorAction SilentlyContinue |
    ForEach-Object {
        $size = (Get-ChildItem $_.FullName -Recurse -File -ErrorAction SilentlyContinue |
                 Measure-Object -Property Length -Sum).Sum
        [PSCustomObject]@{
            Folder = $_.Name
            SizeGB = [math]::Round($size / 1GB, 2)
            Files  = (Get-ChildItem $_.FullName -Recurse -File -ErrorAction SilentlyContinue).Count
        }
    } |
    Sort-Object SizeGB -Descending |
    Select-Object -First 10 |
    Format-Table -AutoSize
Folder          SizeGB Files
------          ------ -----
Windows          23.47 95832
Users            18.01  4823
Program Files    12.34 18293
ProgramData       5.81  3214
Logs              0.08    47

Exclude Specific Subfolders

When certain directories should be excluded from the size calculation:

# Exclude specific folder names using Where-Object
$excludedFolders = @('node_modules', '.git', 'bin', 'obj')

$size = Get-ChildItem 'C:\Projects\MyApp' -Recurse -File -ErrorAction SilentlyContinue |
    Where-Object {
        $folderParts = $_.FullName -split '\\'
        -not ($folderParts | Where-Object { $_ -in $excludedFolders })
    } |
    Measure-Object -Property Length -Sum

'Effective project size: {0:N2} MB' -f ($size.Sum / 1MB)
Effective project size: 12.45 MB

Handling Access Denied Errors

Some directories on Windows deny access even to administrators. Handle this cleanly:

# ErrorAction SilentlyContinue skips inaccessible folders
$total = Get-ChildItem 'C:\Windows' -Recurse -File -ErrorAction SilentlyContinue |
    Measure-Object -Property Length -Sum

# With error logging to see what was skipped
$errors = @()
$total = Get-ChildItem 'C:\Windows' -Recurse -File -ErrorAction SilentlyContinue -ErrorVariable errors |
    Measure-Object -Property Length -Sum

Write-Output "Size (accessible): $([math]::Round($total.Sum/1GB,2)) GB"
Write-Output "Access denied folders: $($errors.Count)"
Size (accessible): 20.34 GB
Access denied folders: 12

Export Folder Size Report to CSV

$report = Get-ChildItem 'C:\' -Directory -ErrorAction SilentlyContinue |
    ForEach-Object {
        $folderPath = $_.FullName
        $files = Get-ChildItem $folderPath -Recurse -File -ErrorAction SilentlyContinue
        $measure = $files | Measure-Object -Property Length -Sum
        [PSCustomObject]@{
            Path        = $folderPath
            SizeGB      = [math]::Round($measure.Sum / 1GB, 3)
            SizeMB      = [math]::Round($measure.Sum / 1MB, 1)
            FileCount   = $measure.Count
        }
    } |
    Sort-Object SizeGB -Descending

$report | Export-Csv 'C:\Reports\folder-sizes.csv' -NoTypeInformation
Write-Output "Report saved: C:\Reports\folder-sizes.csv"
Report saved: C:\Reports\folder-sizes.csv

Common Errors and Fixes

  • Access denied errors break Measure-Object sum: Without -ErrorAction SilentlyContinue, the first access-denied directory stops the entire Get-ChildItem call and Measure-Object receives nothing. Always include this flag when recursing system directories or user profiles.
  • Symlinks counted twice in recursive traversal: If a folder contains symlinks to locations that are also being traversed, files may be counted multiple times. Use Where-Object { -not ($_.Attributes -band [System.IO.FileAttributes]::ReparsePoint) } to skip symlinks in your traversal.

Related Cmdlets / See Also

Wrapping Up

PowerShell folder size reporting is a three-step pipeline: Get-ChildItem with -Recurse -File, Measure-Object with -Sum, and divide by 1MB or 1GB. Always add -ErrorAction SilentlyContinue to handle access-denied folders gracefully. Use the top-10 subfolder pattern to quickly identify disk space culprits. Your next step: schedule this folder size report to run weekly and export to CSV for trend analysis.

Send-Item -To