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

Getting Top Level Folder Report in PowerShell

Posted on May 9, 2013

One of the sessions I presented recently at TechDays San Francisco was on file share management with PowerShell. One of the scripts I demonstrated was for a function to get information for top level folders. This is the type of thing that could be handy to run say against the root of your shared users folder. Or the root of a group share where each subfolder is a share that belongs to a different group. My function takes advantage of a new feature for Get-ChildItem that makes it much easier to retrieve only file or directories. Here's my Get-FolderSize function.

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!
#requires -version 3.0

Function Get-FolderSize {

<#
.Synopsis
Get a top level folder size report
.Description
This command will analyze the top level folders in a given root. It will write
a custom object to the pipeline that shows the number of files in each folder,
the total size in bytes and folder attributes. The output will also include 
files in the root of the specified path.

Sample output:
Name       : DesktopTileResources
Fullname   : C:\windows\DesktopTileResources
Size       : 21094
Count      : 17
Attributes : ReadOnly, Directory

Use the -Force parameter to include hidden directories.
.Example
PS C:\> get-foldersize c:\work | format-table -auto

Path               Name             Size Count Attributes
----               ----             ---- ----- ----------
C:\work            work        252083656   223  Directory
C:\work\atomic     atomic         622445     6  Directory
C:\work\fooby      fooby              18     1  Directory
C:\work\images     images        1470091   118  Directory
C:\work\resources  resources     8542561   143  Directory
C:\work\shell      shell          225161     4  Directory
C:\work\test       test         17198758     4  Directory
C:\work\Test Rig 2 Test Rig 2    4194304     1  Directory
C:\work\test2      test2              40     2  Directory
C:\work\Ubuntu12   Ubuntu12   7656701952     2  Directory
C:\work\widgets    widgets        162703    49  Directory

.Example
PS C:\> get-foldersize c:\users\jeff\ -force | out-gridview -title Jeff
.Notes
Last Updated: May 8, 2013
Version     : 0.9

  ****************************************************************
  * 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/2013/05/getting-top-level-folder-report-in-powershell
.Inputs
None
.Outputs
Custom object
#>

[cmdletbinding()]
Param(
[Parameter(Position=0)]
[ValidateScript({Test-Path $_})]
[string]$Path=".",
[switch]$Force
)

Write-Verbose "Starting $($myinvocation.MyCommand)"
Write-Verbose "Analyzing $path"

#define a hashtable of parameters to splat to Get-ChildItem
$dirParams = @{
Path = $Path
ErrorAction = "Stop"
ErrorVariable = "myErr"
Directory = $True
}

if ($hidden) {
    $dirParams.Add("Force",$True)
}
$activity = $myinvocation.MyCommand

Write-Progress -Activity $activity -Status "Getting top level folders" -CurrentOperation $Path

$folders = Get-ChildItem @dirParams

#process each folder
$folders | 
foreach -begin {
     Write-Verbose $Path
     #initialize some total counters
     $totalFiles = 0
     $totalSize = 0
     #initialize a counter for progress bar
     $i=0

     Try {     
        #measure files in $Path root
        Write-Progress -Activity $activity -Status $Path -CurrentOperation "Measuring root folder" -PercentComplete 0
        #modify dirParams hashtable
        $dirParams.Remove("Directory")
        $dirParams.Add("File",$True)
        $stats = Get-ChildItem @dirParams | Measure-Object -Property length -sum
     }
     Catch {
        $msg = "Error: $($myErr[0].ErrorRecord.CategoryInfo.Category) $($myErr[0].ErrorRecord.CategoryInfo.TargetName)"
        Write-Warning $msg
     }
     #increment the grand totals
     $totalFiles+= $stats.Count
     $totalSize+= $stats.sum

     if ($stats.count -eq 0) {
        #set size to 0 if the top level folder is empty
        $size = 0
     }
     else {
        $size=$stats.sum
     }

     $root = Get-Item -Path $path
     #define properties for the custom object
     $hash = [ordered]@{
         Path = $root.FullName
         Name = $root.Name
         Size = $size
         Count = $stats.count
         Attributes = (Get-Item $path).Attributes
         }
     #write the object for the folder root
     New-Object -TypeName PSobject -Property $hash

    } -process { 
     Try {
        Write-Verbose $_.fullname
        $i++
        [int]$percomplete = ($i/$folders.count)*100
        Write-Progress -Activity $activity -Status $_.fullname -CurrentOperation "Measuring folder" -PercentComplete $percomplete

        #get directory information for top level folders
        $dirParams.Path = $_.Fullname
        $stats = Get-ChildItem @dirParams -Recurse | Measure-Object -Property length -sum
     }
     Catch {
        $msg = "Error: $($myErr[0].ErrorRecord.CategoryInfo.Category) $($myErr[0].ErrorRecord.CategoryInfo.TargetName)"
        Write-Warning $msg
     }
     #increment the grand totals
     $totalFiles+= $stats.Count
     $totalSize+= $stats.sum

     if ($stats.count -eq 0) {
        #set size to 0 if the top level folder is empty
       $size = 0
     }
     else {
        $size=$stats.sum
     }
     #define properties for the custom object
     $hash = [ordered]@{
         Path = $_.FullName
         Name = $_.Name
         Size = $size
         Count = $stats.count
         Attributes = $_.Attributes
        }
     #write the object for each top level folder
     New-Object -TypeName PSobject -Property $hash
 } -end {
    Write-Progress -Activity $activity -Status "Finished" -Completed
    Write-Verbose "Total number of files for $path = $totalfiles"
    Write-Verbose "Total file size in bytes for $path = $totalsize"
 }

 Write-Verbose "Ending $($myinvocation.MyCommand)"
 } #end Get-FolderSize

The function defaults to the local path and gets a collection of all of the top level folders, that is, those found directly in the root. The function then takes the collection of folders and pipes them to ForEach-Object. Most of the time we only use the Process scriptblock with ForEach-Object, but I want to take advantage of the Begin and End blocks as well. In the Begin scriptblock I measure all of the files in the root of the parent path and create a custom object that shows the number of files and total size in bytes. I'm going to get this same information for each child folder as well.

The process scriptblock does just that for each top level folder. This version of my function uses Write-Progress to display progress and in the End script block I have code to complete the progress bar, although It works just fine without it.

Other techniques I'd like to point out are the use of splatting and error handling. You'll notice that I'm using the common -ErrorVariable parameter. After exploring the different types of exceptions I decided I could easily display any errors and the paths In the Catch block. I'm using Write-Warning, but this could just as easily be written to a text file.

The function writes an object like this for every folder.

Path       : C:\windows\Inf
Name       : Inf
Size       : 81926300
Count      : 1265
Attributes : Directory

Here's an example of complete output:

foldersizeBecause I've written objects to the pipeline, I could pipe this to Out-Gridview, export to a CSV file or create an HTML report.

This is just a taste of what you can accomplish with some basic PowerShell commands.

 


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

5 thoughts on “Getting Top Level Folder Report in PowerShell”

  1. petercs says:
    May 9, 2013 at 8:56 pm

    Is there a reason you wouldn’t use (Get-ChildItem -Recure -Force | Where {$_.psiscontainer -eq $false | Measure-object -sum -Property Length).Sum with a custom object? Does it run faster than Get-ChildItem in version 2.0? I typically run into path length limitations based on ridiculous user folder creation with deep paths.

    1. Jeffery Hicks says:
      May 9, 2013 at 9:46 pm

      The main reason is that I wanted to take advantage of the new parameters for Get-Childitem in v3. I haven’t tried it on anything with a really deep path structure.

      1. Jeffery Hicks says:
        May 9, 2013 at 9:54 pm

        In v2, getting just folders using the where clause on my Scripts directory took 2.95 seconds. In v3 using the new -Directory took 148ms. Doing the same for files took 609MS in 2.0 and 534MS in 3.0. I then tested using C:Windows to get files. PowerShell 2.0 took 94.25 seconds and PowerShell 3.0 took 31.15 seconds.

  2. Other (@dvsbobloblaw) says:
    May 10, 2013 at 12:04 pm

    Guess who learned something. -> This.person <-

  3. Pingback: Microsoft Most Valuable Professional (MVP) – Best Posts of the Week around Windows Server, Exchange, SystemCenter and more – #28 - TechCenter - Blog - TechCenter – Dell Community

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