Last week, I demonstrated how to measure a file with PowerShell. This week let's go a step further and measure a folder. I'm going to continue to use Measure-Object although this time I will need to use it to measure numeric property values.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
Here's the complete function after which I'll point out a few key points.
#requires -version 3.0 Function Measure-Folder { <# .SYNOPSIS Measure the size of a folder. .DESCRIPTION This command will take a file path and create a custom measurement object that shows the number of files and the total size. The default size will be in bytes but you can specify a different unit of measurement. The command will format the result accordingly and dynamically change the property name as well. .PARAMETER Path The default is the current path. The command will fail if it is not a FileSystem path. .PARAMETER Unit The default unit of measurement is bytes, but you can use any of the standard PowerShell numeric shortcuts: "KB","MB","GB","TB","PB" .EXAMPLE PS C:\> measure-folder c:\scripts Path Name Count Size ---- ---- ----- ---- C:\scripts scripts 2858 43800390 Measure the scripts folder using the default size of bytes. .EXAMPLE PS C:\> dir c:\scripts -Directory | measure-folder -Unit kb | Sort Size* -Descending | Select -first 5 | format-table -AutoSize Path Name Count SizeKB ---- ---- ----- ------ C:\scripts\GP GP 40 2287.080078125 C:\scripts\Workflow Workflow 64 1253.0185546875 C:\scripts\modhelp modhelp 1 386.4970703125 C:\scripts\stuff stuff 4 309.09375 C:\scripts\ADTFM-Scripts ADTFM-Scripts 76 297.7880859375 Get all the child folders under C:\scripts, measuring the size in KB. Sort the results on the size property in descending order. Then select the first 5 objects and format the results as a table. .NOTES Last Updated: 2/21/2014 Version : 0.9 Learn more: PowerShell in Depth: An Administrator's Guide PowerShell Deep Dives Learn PowerShell 3 in a Month of Lunches Learn PowerShell Toolmaking in a Month of Lunches **************************************************************** * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED * * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF * * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, * * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. * **************************************************************** .LINK https://jdhitsolutions.com/blog/2014/02/friday-fun-the-measure-of-a-folder .LINK Get-ChildItem Measure-Object .INPUTS string or directory .OUTPUTS Custom object #> [cmdletbinding()] Param( [Parameter(Position=0,ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [ValidateScript({Test-Path $_})] [Alias("fullname")] [string]$Path=".", [ValidateSet("Bytes","KB","MB","GB","TB","PB")] [string]$Unit="Bytes" ) Begin { Write-Verbose -Message "Starting $($MyInvocation.Mycommand)" } #begin Process { $Resolved = Resolve-Path -Path $path $Name = Split-Path -Path $Resolved -Leaf #verify we are in the file system if ($Resolved.Provider.Name -eq 'FileSystem') { #define a hash table to hold new object properties $propHash = [ordered]@{ Path=$Resolved.Path Name=$Name } Write-Verbose "Measuring $resolved in $unit" $stats = Get-ChildItem -Path $Resolved -Recurse -File | Measure-Object -sum length Write-Verbose "Measured $($stats.count) files" $propHash.Add("Count",$stats.count) Switch ($Unit) { "bytes" { $propHash.Add("Size",$stats.sum) ; break } "kb" { $propHash.Add("SizeKB",$stats.sum/1KB) ; break } "mb" { $propHash.Add("SizeMB",$stats.sum/1MB) ; break } "gb" { $propHash.Add("SizeGB",$stats.sum/1GB) ; break } "tb" { $propHash.Add("SizeTB",$stats.sum/1TB) ; break } "pb" { $propHash.Add("SizePB",$stats.sum/1PB) ; break } } #switch #write the new object to the pipeline New-Object -TypeName PSobject -Property $propHash } else { Write-Warning "You must specify a file system path." } } #process End { Write-Verbose -Message "Ending $($MyInvocation.Mycommand)" } #end } #end function
The command will use the current path or you can pipe in a directory name, or the output of a Get-ChildItem expression as I show in the help examples. One thing I added is that I test the path to make sure it is a file system path because anything else wouldn't really work.
$Resolved = Resolve-Path -Path $path $Name = Split-Path -Path $Resolved -Leaf #verify we are in the file system if ($Resolved.Provider.Name -eq 'FileSystem') { #define a hash table to hold new object properties $propHash = [ordered]@{ Path=$Resolved.Path Name=$Name } ... else { Write-Warning "You must specify a file system path." }
I resolve the path so that I can get the actual name of the current location (.) and then test the provider. The other interesting feature of this function is that I format the results on the fly.
The function has a Unit parameter which has a default value of bytes. But you can also specify one of the PowerShell numeric shortcuts like KB or GB. In the function I use a Switch construct to create a custom property on the fly.
Switch ($Unit) { "bytes" { $propHash.Add("Size",$stats.sum) ; break } "kb" { $propHash.Add("SizeKB",$stats.sum/1KB) ; break } "mb" { $propHash.Add("SizeMB",$stats.sum/1MB) ; break } "gb" { $propHash.Add("SizeGB",$stats.sum/1GB) ; break } "tb" { $propHash.Add("SizeTB",$stats.sum/1TB) ; break } "pb" { $propHash.Add("SizePB",$stats.sum/1PB) ; break } } #switch
Because there can only be a single value for $Unit, I'm including the Break directive so that PowerShell won't try to process any other potential matches in the Switch construct. Realistically, there's a negligible performance gain in this situation but I wanted you to see how this works.
PS C:\> dir D:\VM -Directory | measure-folder -Unit MB | Out-GridView -Title "VM Size"
I've taken some basic commands you could use interactively such as Get-ChildItem and Measure-Object and built a tool around them using a hashtable of properties to create a custom object. I hope you pick up a tip or two from this. If you have any questions about what I'm doing or why, please don't hesitate to ask because someone else might have the same question.
Enjoy your weekend!
1 thought on “Friday Fun: The Measure of a Folder”
Comments are closed.