Tasks/BuiltIn/File/Get-PathSize.ps1
|
<#
.SYNOPSIS Calculate the size of a file or directory including all subdirectories .DESCRIPTION This task calculates the total size of a file or directory, including all subdirectories and files. Can display results in various units (Bytes, KB, MB, GB, TB) and optionally provide a breakdown by file type. .PARAMETER Path Path to the file or directory .PARAMETER Unit Unit to display size in. Valid values: Bytes, KB, MB, GB, TB. Default: MB .PARAMETER IncludeDetails Include breakdown of file types and counts .NOTES TaskName: File.GetPathSize Version: 1.0.0 Author: Toolbox Tags: File, Directory, Storage RequiresElevation: False SupportedOS: Windows, Linux, MacOS PSEdition: Desktop, Core MinPSVersion: 5.1 Timeout: 300 .EXAMPLE Invoke-Task -TaskName 'File.GetPathSize' -Computers 'localhost' -TaskParameters @{ Path = 'C:\Temp' } .EXAMPLE Invoke-Task -TaskName 'File.GetPathSize' -Computers 'localhost' -TaskParameters @{ Path = 'C:\Temp'; Unit = 'GB'; IncludeDetails = $true } #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$Path, [Parameter()] [ValidateSet('Bytes', 'KB', 'MB', 'GB', 'TB')] [string]$Unit = 'MB', [Parameter()] [switch]$IncludeDetails ) try { Write-Verbose "Calculating size of path: $Path" # Validate path exists if (-not (Test-Path -Path $Path)) { throw "Path not found: $Path" } $item = Get-Item -Path $Path -ErrorAction Stop $isDirectory = $item.PSIsContainer Write-Verbose "Path type: $(if ($isDirectory) { 'Directory' } else { 'File' })" # Calculate size $totalBytes = 0 $fileCount = 0 $directoryCount = 0 $fileTypeStats = @{} if ($isDirectory) { Write-Verbose "Enumerating all items in directory..." $allItems = Get-ChildItem -Path $Path -Recurse -Force -ErrorAction SilentlyContinue foreach ($file in $allItems) { if ($file.PSIsContainer) { $directoryCount++ } else { $fileCount++ $totalBytes += $file.Length # Track file type statistics if requested if ($IncludeDetails) { $extension = if ($file.Extension) { $file.Extension.ToLower() } else { '(no extension)' } if (-not $fileTypeStats.ContainsKey($extension)) { $fileTypeStats[$extension] = @{ Count = 0 Size = 0 } } $fileTypeStats[$extension].Count++ $fileTypeStats[$extension].Size += $file.Length } } } } else { $fileCount = 1 $totalBytes = $item.Length if ($IncludeDetails) { $extension = if ($item.Extension) { $item.Extension.ToLower() } else { '(no extension)' } $fileTypeStats[$extension] = @{ Count = 1 Size = $item.Length } } } # Convert to requested unit $divisor = switch ($Unit) { 'Bytes' { 1 } 'KB' { 1KB } 'MB' { 1MB } 'GB' { 1GB } 'TB' { 1TB } } $sizeInUnit = [math]::Round($totalBytes / $divisor, 2) Write-Verbose "Total size: $sizeInUnit $Unit ($totalBytes bytes)" Write-Verbose "Files: $fileCount, Directories: $directoryCount" # Build result object $result = [PSCustomObject]@{ Path = $Path Type = if ($isDirectory) { 'Directory' } else { 'File' } TotalSize = $sizeInUnit Unit = $Unit TotalSizeBytes = $totalBytes FileCount = $fileCount DirectoryCount = $directoryCount } # Add file type breakdown if requested if ($IncludeDetails -and $fileTypeStats.Count -gt 0) { $fileTypeBreakdown = foreach ($ext in ($fileTypeStats.Keys | Sort-Object)) { [PSCustomObject]@{ Extension = $ext FileCount = $fileTypeStats[$ext].Count Size = [math]::Round($fileTypeStats[$ext].Size / $divisor, 2) Unit = $Unit SizeBytes = $fileTypeStats[$ext].Size } } $result | Add-Member -NotePropertyName 'FileTypeBreakdown' -NotePropertyValue $fileTypeBreakdown } $result } catch { Write-Error "Failed to calculate path size: $_" throw } |