Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Measuring Folders with PowerShell One More Time

Posted on July 22, 2015July 22, 2015

I know I just posted an update to my Measure-Folder function but I couldn't help myself and now I have an update to the update. Part of the update came as the result of a comment asking about formatting results to a certain number of decimal places. I typically the Round() method from the Math .NET class.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!
PS C:\> [math]::Round(1234.56789,2)
1234.57
PS C:\> [math]::Round(1234.5678900123,4)
1234.5679

So I added a parameter, Round, to automatically round to a certain number of decimal points. The default is 2 but you can enter any value between 0 and 10. If you use 0 the effect is to treat the value as an integer.

The other change I made was to simplify the code. My intention when creating a PowerShell tool is not have duplicate commands, or commands that are very, very similar. In last week's version I used a Switch statement to dynamically create properties and values. But each item was practically the same except for the unit of measurement. So instead I came up with a hash table of units.

$unitHash = @{
  Bytes = 1
  KB = 1KB
  MB = 1MB
  GB = 1GB
  TB = 1TB
  PB = 1PB
}

With this I can use the hashtable key as the part of property name, and the value for formatting the result.

$value = [Math]::Round($stats.sum/$UnitHash.item($unit),$Round)

The property name is created on the fly for anything other than the default "bytes".

$Label = "Size"
if ($unit -ne 'bytes') {
  $label+= $($unit.ToUpper())
}
$propHash.Add($label,$value)

I use the same process if the user wants the average. Here's the complete revised function.

#requires -version 4.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 Average
Get the average file size. This will be formatted with the same unit as the total size.

.PARAMETER NoRecurse
The default behavior is to recurse through all subfolders. But you can suppress that by using -NoRecurse.

.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"

.PARAMETER Round
The number of decimal points to round the sum and average values. The default is 2. Use a value of 10 to not round. The maximum value is 10.

.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.08
C:\scripts\Workflow      Workflow         64         1253.02
C:\scripts\modhelp       modhelp           1          386.49
C:\scripts\stuff         stuff             4          309.09
C:\scripts\ADTFM-Scripts ADTFM-Scripts    76          297.78

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.

.EXAMPLE
PS C:\> measure-folder $env:temp -Average -unit MB -round 10

Path   : C:\Users\Jeff\AppData\Local\Temp
Name   : Temp
Count  : 64626
SizeMB : 6769.94603252411
AvgMB  : 0.104755764437287

Measure all the %TEMP% folder, including a file average all formatted in MB with no rounding
.NOTES
Last Updated: July 22, 2015
Version     : 2.2

Originally published at https://jdhitsolutions.com/blog/scripting/3715/friday-fun-the-measure-of-a-folder/

Learn more about PowerShell:
Essential PowerShell Learning Resources
**************************************************************** * 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 Get-ChildItem Measure-Object .INPUTS string or directory .OUTPUTS Custom object #> [cmdletbinding()] Param( [Parameter(Position=0,ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [ValidateScript({ if (Test-Path $_) { $True } else { Throw "Cannot validate path $_" } })] [Alias("fullname")] [string]$Path = ".", [switch]$NoRecurse, [Alias("avg")] [switch]$Average, [ValidateSet("bytes","KB","MB","GB","TB","PB")] [string]$Unit = "bytes", [ValidateRange(0,10)] [int]$Round = 2 ) Begin { Write-Verbose -Message "Starting $($MyInvocation.Mycommand)" #hash table of parameters to Splat to Get-ChildItem $dirHash = @{ File = $True Recurse = $True } if ($NoRecurse) { Write-Verbose "No recurse" $dirHash.remove("recurse") } #hash table of parameters to splat to measure-Object $measureHash = @{ Property = "length" Sum = $True } if ($Average) { Write-Verbose "Including Average" $measureHash.Add("Average",$True) } Write-Verbose "Rounding to $Round decimal points." } #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" $dirHash.Path = $Resolved $stats = Get-ChildItem @dirHash | Measure-Object @measureHash Write-Verbose "Measured $($stats.count) files" $propHash.Add("Count",$stats.count) $unitHash = @{ Bytes = 1 KB = 1KB MB = 1MB GB = 1GB TB = 1TB PB = 1PB } $value = [Math]::Round($stats.sum/$UnitHash.item($unit),$Round) $Label = "Size" if ($unit -ne 'bytes') { $label+= $($unit.ToUpper()) } $propHash.Add($label,$value) #repeat process for Average if ($Average) { $value = [Math]::Round($stats.average/$UnitHash.item($unit),$Round) $Label = "Avg" if ($unit -ne 'bytes') { $label+= $($unit.ToUpper()) } $propHash.Add($label,$value) } #if Average #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 results are the same, with the addition of the rounding option.

I swear this is the last change. Unless someone gives me a cool idea! Enjoy.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

4 thoughts on “Measuring Folders with PowerShell One More Time”

  1. Yomodo says:
    July 22, 2015 at 4:42 pm

    How about long path support?
    Perhaps even some speed increase?

    https://github.com/alphaleonis/AlphaFS/wiki/PowerShell

    1. Jeffery Hicks says:
      July 22, 2015 at 5:09 pm

      Long paths are always an issue in Windows. Performance could be tweaked by using .NET directly, but then that takes me out of creating a PowerShell script and into development. If someone has a situation where those things are critical, PowerShell may not be the best tool for the job.

  2. Larry Weiss says:
    July 23, 2015 at 4:36 pm

    Why
    #requires -version 4.0
    ?

    1. Jeffery Hicks says:
      July 23, 2015 at 4:54 pm

      Primarily because that is what I tested with. I suspect it will work with v3. Change 4 to 3 and give it a go.

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d