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.