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

Measure that Folder with PowerShell Revisited

Posted on July 15, 2015July 22, 2015

Last year I posted a PowerShell function to measure the size of a folder. I recently had a need to use it again, and realized it needed a few tweaks. By default, the original version recursively searched through all subfolders. But there may be situations where you only want to measure the top level folder, so I added a –NoRecurse parameter. I also added a parameter to display an average value as well.

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!


Figure 1 Measuring the Temp folder in GB


Figure 2 Measuring my Documents folder including average size in KB

Here is the updated function:

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

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

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

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.
.NOTES
Last Updated: July 13, 2015
Version     : 2.0

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" ) 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) } } #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) Switch ($Unit) { "bytes" { $propHash.Add("Size",$stats.sum) if ($average) { $propHash.Add("Avg",$stats.Average) } break } "kb" { $propHash.Add("SizeKB",$stats.sum/1KB) if ($average) { $propHash.Add("AvgKB",$stats.Average/1KB) } break } "mb" { $propHash.Add("SizeMB",$stats.sum/1MB) if ($average) { $propHash.Add("AvgMB",$stats.Average/1MB) } break } "gb" { $propHash.Add("SizeGB",$stats.sum/1GB) if ($average) { $propHash.Add("AvgGB",$stats.Average/1GB) } break } "tb" { $propHash.Add("SizeTB",$stats.sum/1TB) if ($average) { $propHash.Add("AvgTB",$stats.Average/1TB) } break } "pb" { $propHash.Add("SizePB",$stats.sum/1PB) if ($average) { $propHash.Add("AvgPB",$stats.Average/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

I hope you'll let me know what you think or what additional features would be helpful.

Update: For an even newer version of this function go here.


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

7 thoughts on “Measure that Folder with PowerShell Revisited”

  1. Mike Shepard says:
    July 16, 2015 at 11:40 am

    What do you think about creating a $Units hashtable to eliminate the switch statement? Seems like a good opportunity to me because the switch branches are very similar.

    1. Jeffery Hicks says:
      July 16, 2015 at 11:52 am

      That is a terrific alternative.

    2. Jeffery Hicks says:
      July 16, 2015 at 12:51 pm

      In place of the Switch statement, you could use code like this:

      $unitHash = @{
      Bytes = 1
      KB = 1KB
      MB = 1MB
      GB = 1GB
      TB = 1TB
      PB = 1PB
      }
      $value = $stats.sum/$UnitHash.item($unit)
      $Label = "Size"
      if ($unit -ne 'bytes') {
      $label+= $($unit.ToUpper())
      }

      $propHash.Add($label,$value)
      #repeat process for Average
      if ($Average) {
      $value = $stats.average/$UnitHash.item($unit)
      $Label = "Avg"
      if ($unit -ne 'bytes') {
      $label+= $($unit.ToUpper())
      }
      $propHash.Add($label,$value)
      } #if Average

  2. Larry Weiss says:
    July 17, 2015 at 12:26 am

    Thanks for sharing the code to Measure-Folder
    One missing thing is help text for the -Average switch.

    1. Jeffery Hicks says:
      July 17, 2015 at 8:18 am

      I went ahead and added a little something.

  3. Manfred Zysk says:
    July 22, 2015 at 12:19 pm

    Jeffery, I like the simplicity of this. What would be an easy method to round off (to the thousandths place, for example) instead of having “6.611275422…GB” in Figure 1?

    Thank you,

    Manfred

    1. Jeffery Hicks says:
      July 22, 2015 at 12:50 pm

      I find it easiest to use the Round() method from the [MATH] class. Here’s a sample that would round to 2 decimal points.
      $propHash.Add(“SizeTB”,[math]::round($stats.sum/1TB,2))
      if ($average) {
      $propHash.Add(“AvgTB”,[math]::Round($stats.Average/1TB,2))
      Perhaps I should add a rounding parameter. Or you can!
      }

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