Exploring Folder Structures (Part 2)

by Mar 18, 2021

With just a couple of cmdlets, you can examine folder structures and i.e. return the sizes of subfolders in a folder tree.

Here is an example that returns both total and relative folder sizes:

# specify the folder that you want to discover
# $home is the root folder of your user profile
# you can use any folder: $path = 'c:\somefolder'
$path = $HOME

# specify the depth you want to examine (the number of levels you'd like
# to dive into the folder tree)
$Depth = 3

# find all subfolders...
Get-ChildItem $path -Directory -Recurse -ErrorAction Ignore -Depth $Depth  |
ForEach-Object {
  Write-Progress -Activity 'Calculating Folder Size' -Status $_.FullName

  # return the desired information as a new custom object 
  [pscustomobject]@{
    RelativeSize = Get-ChildItem -Path $_.FullName -File -ErrorAction Ignore | & { begin { $c = 0 } process { $c += $_.Length } end { $c }}
    TotalSize = Get-ChildItem -Path $_.FullName -File -Recurse -ErrorAction Ignore | & { begin { $c = 0 } process { $c += $_.Length } end { $c }}
    FullName  = $_.Fullname.Substring($path.Length+1)
  }
} 

Note how the code sums up the sizes of all files: it calls a script block with begin, process and end-blocks. The begin block gets executed before the pipeline starts and sets the counting variable to zero. The process block gets repeated for each incoming pipeline object and adds the file size in the Length property to the counter. The end block gets executed when the pipeline is done and returns the calculated sum.

This approach is much faster than using ForEach-Object and still a bit faster than using Measure-Object. You can count all kinds of things this way. This code counts the number of objects emitted by Get-Service:

# counting number of objects
Get-Service | & { begin { $c = 0 } process { $c++ } end { $c }}

Note that this is a “streaming” approach without the necessity to store all objects in memory. With small numbers of objects, you could as well use the “download” approach and store all elements in memory, then use the Count property:

(Get-Service).Count


Twitter This Tip! ReTweet this Tip!