functions/Get-FolderSizeInfo.ps1
Function Get-FolderSizeInfo { [cmdletbinding()] [alias('gsi')] [OutputType('FolderSizeInfo')] Param( [Parameter( Position = 0, Mandatory, HelpMessage = 'Enter a file system path like C:\Scripts.', ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [alias('PSPath')] [string[]]$Path, [Parameter(HelpMessage = 'Include hidden directories')] [switch]$Hidden, [Parameter(HelpMessage = 'Enable support for long file and folder names.')] [alias('lfn', 'EnableLN')] [switch]$EnableLongFileName ) Begin { Write-Verbose "Starting $($MyInvocation.MyCommand)" #a function to recurse and get all non-hidden directories #This function will only be called on Windows PowerShell systems. Function _EnumDir { [cmdletbinding()] Param([string]$Path, [switch]$Hidden) # write-host $path -ForegroundColor cyan $path = Convert-Path -LiteralPath $path $ErrorActionPreference = 'Stop' try { $di = [System.IO.DirectoryInfo]::new($path) if ($hidden) { $top = ($di.GetDirectories()).Where( { $_.attributes -notmatch 'ReparsePoint'}) } else { $top = ($di.GetDirectories()).Where( { $_.attributes -notmatch 'hidden|ReparsePoint' }) } $top foreach ($t in $top) { $params = @{ Path = $t.FullName Hidden = $Hidden } _EnumDir @params } } Catch { Write-Warning "Failed on $path. $($_.exception.message)." } } # _EnumDir } #Begin Process { foreach ($item in $path) { #Enable long file name support Issue #134 if ($EnableLongFileName) { Write-Verbose 'Enabling long file name support' $item = if ($item -match '^\\\\') { "\\?\UNC\$($item.substring(2))" } else { "\\?\$item" } } #need to convert to file system paths $cPath = (Convert-Path -LiteralPath $item) Write-Verbose "Measuring $cPath on $([System.Environment]::MachineName)" if (Test-Path -LiteralPath $cPath) { $d = [System.IO.DirectoryInfo]::new($cPath) #Changed from ArrayList to generic list 28 Feb 2023 JDH #suggestion from @ScriptingStudio Issue #134 #[System.Collections.ArrayList]::new() $files = [System.Collections.Generic.list[System.IO.FileInfo]]::New() If ($PSVersionTable.PSVersion.major -gt 5 ) { #this .NET class is not available in Windows PowerShell 5.1 $opt = [System.IO.EnumerationOptions]::new() $opt.RecurseSubdirectories = $True if ($hidden) { Write-Verbose 'Including hidden files' $opt.AttributesToSkip = 'SparseFile', 'ReparsePoint' } else { $opt.AttributesToSkip = 'Hidden','SparseFile', 'ReparsePoint' } Write-Verbose "Skipping attributes $($opt.AttributesToSkip)" [System.IO.FileInfo[]]$data = $($d.GetFiles('*', $opt)) Write-Verbose "Found $($data.count) files(s)" if ($data -AND $data.count -gt 1) { $files.AddRange($data) } elseif ($data -AND $data.count -eq 1) { $files.Add($data[0]) } } #if newer than Windows PowerShell 5.1 else { Write-Verbose 'Using legacy code' #need to account for errors when accessing folders without permissions # get files in the root of the folder if ($hidden) { Write-Verbose 'Including hidden files' $data = $d.GetFiles() } else { #get files in current location $data = $($d.GetFiles()).Where({ $_.attributes -notmatch 'hidden|ReparsePoint' }) } Write-Verbose "Found $($data.count) files" if ($data -AND $data.count -gt 1) { $files.AddRange([System.IO.FileInfo[]]$data) } elseif ($data -AND $data.count -eq 1) { $files.Add($data[0]) } #get a list of all non-hidden sub-folders Write-Verbose "Getting sub-folders (Hidden = $Hidden)" $eParam = @{ Path = $cPath Hidden = $hidden } $all = _EnumDir @eParam #get the files in each subfolder if ($all) { Write-Verbose "Getting files from $($all.count) sub-folders" ($all).Foreach( { $currentFolder = $_.FullName Write-Verbose $CurrentFolder $ErrorActionPreference = 'Stop' Try { if ($hidden) { $data = (([System.IO.DirectoryInfo]$CurrentFolder).GetFiles()) } else { $data = (([System.IO.DirectoryInfo]$CurrentFolder).GetFiles()).where({ $_.Attributes -notmatch 'Hidden' }) } Write-Verbose "Found $($data.count) files" if ($data -AND $data.count -gt 1) { $files.AddRange([System.IO.FileInfo[]]$data) } elseif ($data -AND $data.count -eq 1) { $files.Add($data[0]) } } Catch { Write-Warning "Failed on $CurrentFolder. $($_.exception.message)." #clearing the variable as a precaution Clear-Variable data } }) } #if $all } #else 5.1 If ($files.count -gt 0) { Write-Verbose "Found $($files.count) total files" $stats = $Files | Measure-Object -Property length -Sum $totalFiles = $stats.count $totalSize = $stats.sum } else { Write-Verbose 'Found an empty folder' $totalFiles = 0 $totalSize = 0 } [PSCustomObject]@{ PSTypename = 'FolderSizeInfo' Computername = [System.Environment]::MachineName Path = $cPath Name = $(Split-Path -Path $cPath -Leaf) TotalFiles = $totalFiles TotalSize = $totalSize } } #test path else { Write-Warning "Can't find $Path on $([System.Environment]::MachineName)" } } #foreach item } #process End { Write-Verbose "Ending $($MyInvocation.MyCommand)" } } #close function <# C:\Windows from Explorer Contains 206345 files contains 61817 folders total size 30.6gb size on disk 30.7 gb #> |