Expert Commentary: 2012 Scripting Games Advanced Event 4

Summary: Microsoft MVP, Chad Miller, provides expert commentary for 2012 Scripting Games Advanced Event 4.

Microsoft Scripting Guy, Ed Wilson, is here. Chad Miller is the expert commentator for Advanced Event 4.

Chad is a senior manager of database administration at Raymond James Financial. Chad has worked with Microsoft SQL Server since 1999, and he has been automating administration tasks by using Windows PowerShell since 2007. Chad is a Windows PowerShell MVP and the project coordinator and developer of the Windows PowerShell-based CodePlex project, SQL Server PowerShell Extensions (SQLPSX). Chad leads the Tampa PowerShell User Group, and he is a frequent speaker at users groups, SQL Saturdays, and Code Camps.

Blog: Sev17—SQL Server, PowerShell, and so on
Twitter: @cmille19

The function Get-FolderSize reports the folder size of the specified folder and all subfolders. A path (folder) must be provided to the Get-FolderSize function.

To display the folder size for the current directory, use:


Image of command output

To display folder size information for a list of folders, use:

Get-FolderSize Desktop,Downloads,DropBox


Get-Content folders.txt | Get-FolderSize

The code for this script is shown here:




Gets folder size.


The Get-FolderSize function gets the folder size at the specified location.


Get-FolderSize .

This command gets the folder size of the current directory. The dot (.) represents the item at the current location.


Get-FolderSize C:\Windows

This command the folder size of the Windows directory.



        You can pipe a string that contains a path to Get-FolderSize.




Version History

v1.0   – Chad Miller – Initial release


function Get-FolderSize








    BEGIN {

        function Format-FolderSize




            if ($Size -ge 1GB) {

                “{0:N2} Gigabytes” -f $($Size/1GB)


            elseif ($Size -ge 1MB) {

                “{0:N2} Megabytes” -f $($Size/1MB)


            else {

                “{0:N2} Bytes” -f $Size



        } #Format-FolderSize



        Get-Item $Path |  Foreach-Object {$_; $_ | Get-Childitem -Recurse} |

        Where-Object {$_.PSIsContainer}  |

        Select-Object FullName, @{name=’Size’;expression={$(Get-ChildItem $_.FullName -Recurse | Measure-Object -Sum -Property Length).Sum}} |

        Sort-Object Size -Descending |

        Select-Object @{name=”Folder”;expression={$_.FullName}}, @{name=’Size of Folder’;expression={$(Format-FolderSize -Size $_.Size)}}


    END {}



} #Get-FolderSize

The main section of script is shown here:

The approach I took to solve this problem follows the structures of the PROCESS block of the script. I would start with step one and proceed to the next steps only when the results from the previous steps have been achieved.

  1. Use the Get-Item cmdlet to retrieve information about the specified path. The ForEach-Object cmdlet returns the item, and Get-ChildItem is called recursively to retrieve all child items.
  2. Apply a filter using Where-Object, which tests whether the PSIsContainer property is true, which means the item is of type directory.
  3. After we have the specified directory and all subdirectories, use select-object to retrieve the FullName property, and add a Size property by using a hash table with name and expression keys. The expression uses the Measure-Object cmdlet, summing on the Length property.
  4. Now sort the object by the newly added Size property.
  5. Finally, use the Select-Object cmdlet to emit a custom object with Folder and Size of Folder properties. The Size of Folder property makes use of the function Format-FolderSize, which is defined in the BEGIN block of Get-FolderSize. The Format-FolderSize handles formatting the folder size in the appropriate unit of measurement (gigabytes, megabytes, or bytes). By defining the Format-Folder function in the BEGIN block, the function is private and not visible outside of the Get-FolderSize function.


The 2012 Scripting Games Guest Commentator Week will continue tomorrow when we will present the scenario for Event 5.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Comments (5)

  1. mjolinor says:

    I went a  different way on this one.

    $DirCounts = @{}

    get-childitem $Directory -Recurse |

      where {-not ($_.psiscontainer)} |

          select directoryname,length |

           foreach-object {

            $DirPath = $_.directoryname

              While ($DirPath -ge $Directory){

                  $DirCounts.$DirPath += $_.length

                  $DirPath = $DirPath | Split-Path -Parent



    $dircounts.getenumerator() | sort value -Descending

    While admittedly a little unconventional, it has the advantage of only requiring one directory read operation. That could mean a substantial performace advantage depending on how extensive the directory structure is that you're reporting on.

  2. hemanth says:

    @mjolinor: Wouldn't the below have been easier instead of foreach? Or, am I missing something?

    Get-ChildItem $Directory -Recurse |

       Where-Object {-not ($_.psiscontainer)} |

           Group-Object -Property DirectoryName|

               Select-Object Name, @{Name="DirSize";Expression={ (($_.Group|Measure-Object -Property Length -Sum).Sum/1MB)} } |

    Sort-Object -Property DirSize -Descending | Select -First 3 | Format-Table -AutoSize

    Name DirSize

    —- ——-

    C:Hemanth-SQLServerOutlook-PST 615.2009392

    C:Hemanth-SQLServerData_From_Old_Laptop 510.4251547

    C:Hemanth-SQLServerMSSQLBOL 281.6665039

  3. Rob Campbell says:

    @Hemanth I believe that will report on the size of the files in each directory. If I'm reading the event criteria correctly, they want the size of the files in each directory and all of it's subdirectories.  That means that for any given file it's length must be attributed to not just it's immediate directory, but every parent directory in it's directory path, back to the base directory that's being reported on.

  4. hemanth says:


    So, something like this would work?

    Get-ChildItem $Directory -Recurse |

    Where-Object {-not ($_.psiscontainer)} |

    Group-Object -Property DirectoryName|

    Select-Object Name, @{Name="DirSize";Expression={ (($_.Group|Measure-Object -Property Length -Sum).Sum)} } |

    Group-Object -Property Name | Select-Object Name, @{Name="DirSizes";Expression={(($_.Group|Measure-Object -Property DirSize -Sum).Sum)}} |

    Sort-Object -Property Name | Select -First 10 | Format-Table -AutoSize

    Name                                                                  DirSizes

    —-                                                                  ——–

    C:Hemanth-SQLServer                                                  20046514

    C:Hemanth-SQLServer2012SG                                             632674

    C:Hemanth-SQLServer2012SGAdvancedEventsAdvancedEvent_2               24942

    C:Hemanth-SQLServer2012SGAdvancedEventsAdvancedEvent_2otherssols     1790

    C:Hemanth-SQLServer2012SGAdvancedEventsAdvancedEvent_3otherssols     2641

    C:Hemanth-SQLServer2012SGAdvancedEventsAdvancedEvent_4                4611

    C:Hemanth-SQLServer2012SGAdvancedEventsAdvancedEvent_4otherssols     2720

    C:Hemanth-SQLServer2012SGAdvancedEventsAdvancedEvent_5                8374

    C:Hemanth-SQLServer2012SGAdvancedEventsAdvancedEvent_5otherssols    10454

    C:Hemanth-SQLServer2012SGAdvancedEventsAdvancedEvent_6                4980

  5. Rob Campbell says:

    @Hermanth – I ran both of them against a test directory and got different rusults.

    It look like that misses any directory that only has subdirectories in it.