0

Get Directory Tree Size Using Powershell (Recursive)

The other day I got some alerts saying that one of our file servers was running out of space. Typically, I would just go into VMware vCenter, expand the disk and call it a day. The problem was that this was a relatively new server with several terabytes of disk space. I thought it to be highly unusual that it could be filled up so fast so I wanted to see what folders were taking the most space remotely. I know there are programs such as windirstat and treesize but I didn’t necessarily want to install anything on my server, much less worry about patching it or removing it later. I wanted something a bit more portable and most of all, I wanted something clean! I decided I was going to write a Powershell script to get folder sizes on remote computers and ultimately came up with Get Directory Tree Size Using Powershell.

 
The goal of the script was to have Powershell get all files in a directory and subdirectories with size. As mentioned above I also wanted it to be portable so I wanted to make sure it was able get folder sizes for remote computers. I was in luck because Get-ChildItem -Recurse does exactly that, and it does it very quickly. The best thing of all is that it supports remote UNC paths, mapped drives and local drives. This would be the base of the function.

Things to Note

There are a couple of things I wanted to highlight and/or clarify just in case it might be misleading.

  • Get-DirectoryTreeSize supports remote UNC (Network), Local and Mapped Drives
  • It uses Get-Childitem and Measure-Object as the base cmdlets to quickly calculate data
  • Only specifying the path parameter will show files, folders and size for the specified directory
  • Recurse shows files, folders and sizes for each directory respectively
  • To avoid long subfolder strings, subfolders will display “.\” instead of $Path
  • AllItemsAndAllFolders will get all files, all folders and the total size for the specified directory and all subdirectories
  • Get-DirectoryTreeSize -Path C:\Temp -Recurse | Sort-Object FolderSizeInMB -Descending will quickly get the largest folder in your query
  • There are 3 decimal places so smaller files won’t show 0 size

 
If you have any questions feel free to drop me a comment and I’ll do my best to get back to you.

Get Directory Tree Size Using Powershell

Function Get-DirectoryTreeSize {
<#
.SYNOPSIS
    This is used to get the file count, subdirectory count and folder size for the path specified. The output will show the current folder stats unless you specify the "AllItemsAndAllFolders" property.
    Since this uses Get-ChildItem as the underlying structure, this supports local paths, network UNC paths and mapped drives.

.NOTES
    Name: Get-DirectoryTreeSize
    Author: theSysadminChannel
    Version: 1.0
    DateCreated: 2020-Feb-11


.LINK
    https://thesysadminchannel.com/get-directory-tree-size-using-powershell -


.PARAMETER Recurse
    Using this parameter will drill down to the end of the folder structure and output the filecount, foldercount and size of each folder respectively.

.PARAMETER AllItemsAndAllFolders
    Using this parameter will get the total file count, total directory count and total folder size in MB for everything under that directory recursively.

.EXAMPLE
    Get-DirectoryTreeSize "C:\Some\Folder"

    Path            FileCount DirectoryCount FolderSizeInMB
    ----            --------- -------------- --------------
    C:\Some\folder          3              3          0.002

.EXAMPLE
    Get-DirectoryTreeSize "\\MyServer\Folder" -Recurse

    Path                 FileCount DirectoryCount FolderSizeInMB
    ----                 --------- -------------- --------------
    \\MyServer\Folder            2              1         40.082
    .\Subfolder                  1              0         26.555

.EXAMPLE
    Get-DirectoryTreeSize "Z:\MyMapped\folder" -AllItemsAndAllFolders

    Path                  TotalFileCount TotalDirectoryCount TotalFolderSizeInMB
    ----                  -------------- ------------------- -------------------
    Z:\MyMapped\folder                 3                   1              68.492

#>

[CmdletBinding(DefaultParameterSetName="Default")]

param(
    [Parameter(
        Position = 0,
        Mandatory = $true
    )]
    [string]  $Path,



    [Parameter(
        Mandatory = $false,
        ParameterSetName = "ShowRecursive"
    )]
    [switch]  $Recurse,



    [Parameter(
        Mandatory = $false,
        ParameterSetName = "ShowTopFolderAllItemsAndAllFolders"
    )]
    [switch]  $AllItemsAndAllFolders
)

    BEGIN {
        #Adding a trailing slash at the end of $path to make it consistent.
        if (-not $Path.EndsWith('\')) {
            $Path = "$Path\"
        }
    }

    PROCESS {
        try {
            if (-not $PSBoundParameters.ContainsKey("AllItemsAndAllFolders") -and -not $PSBoundParameters.ContainsKey("Recurse")) {
                $FileStats = Get-ChildItem -Path $Path -File -ErrorAction Stop | Measure-Object -Property Length -Sum
                $FileCount = $FileStats.Count
                $DirectoryCount = Get-ChildItem -Path $Path -Directory | Measure-Object | select -ExpandProperty Count
                $SizeMB =  "{0:F3}" -f ($FileStats.Sum / 1MB) -as [decimal]

                [PSCustomObject]@{
                    Path                 = $Path#.Replace($Path,".\")
                    FileCount            = $FileCount
                    DirectoryCount       = $DirectoryCount
                    FolderSizeInMB       = $SizeMB
                }
            }

            if  ($PSBoundParameters.ContainsKey("AllItemsAndAllFolders")) {
                $FileStats = Get-ChildItem -Path $Path -File -Recurse -ErrorAction Stop | Measure-Object -Property Length -Sum
                $FileCount = $FileStats.Count
                $DirectoryCount = Get-ChildItem -Path $Path -Directory -Recurse | Measure-Object | select -ExpandProperty Count
                $SizeMB =  "{0:F3}" -f ($FileStats.Sum / 1MB) -as [decimal]

                [PSCustomObject]@{
                    Path                 = $Path#.Replace($Path,".\")
                    TotalFileCount       = $FileCount
                    TotalDirectoryCount  = $DirectoryCount
                    TotalFolderSizeInMB  = $SizeMB
                }
            }

            if ($PSBoundParameters.ContainsKey("Recurse")) {
                Get-DirectoryTreeSize -Path $Path
                $FolderList = Get-ChildItem -Path $Path -Directory -Recurse | select -ExpandProperty FullName

                if ($FolderList) {
                    foreach ($Folder in $FolderList) {
                        $FileStats = Get-ChildItem -Path $Folder -File | Measure-Object -Property Length -Sum
                        $FileCount = $FileStats.Count
                        $DirectoryCount = Get-ChildItem -Path $Folder -Directory | Measure-Object | select -ExpandProperty Count
                        $SizeMB =  "{0:F3}" -f ($FileStats.Sum / 1MB) -as [decimal]

                        [PSCustomObject]@{
                            Path                 = $Folder.Replace($Path,".\")
                            FileCount            = $FileCount
                            DirectoryCount       = $DirectoryCount
                            FolderSizeInMB       = $SizeMB
                        }
                        #clearing variables
                        $null = $FileStats
                        $null = $FileCount
                        $null = $DirectoryCount
                        $null = $SizeMB
                    }
                }
            }
        } catch {
            Write-Error $_.Exception.Message
        }

    }

    END {}

}

When you call the function and only specify the path parameter, here is what it looks like.

Get-DirectoryTreeSize

In this example, I have 3 files and 2 subdirectories, totalling 66678.063 MB (65.11 GB) for that current directory

Get-DirectoryTreeSize -AllItemsAndAllFolders

There are a total of 12 files and 5 directories amounting to 181759.929 MB (177.49 GB) – This for this directory and all subdirectories. This is also equivalent to right clicking the folder and selecting properties.

Finally, we can get the folder tree recursively so I’m going to run the same script locally (thanks to its portability), from my other computer that’s hosting the backup folder.

Get-DirectoryTreeSize-Recurse

The Recurse parameter allows you to drill down all folders and view stats. You can also sort by FolderSizeInMB and see which folder has the most space.

 

Another thing to note is that I wanted to shorten the display of the subfolders so it doesn’t push the file, directory and size counts off the screen. For this I replaced the original $Path location with “.\” so it’s relative to $Path.

So hopefully you were able to make use of the Powershell script to get directory tree size including all subfolders. I’m pretty stoked how quickly it was able to process remote servers and I’m sure I’ll be adding this to my list of audit tasks. It’s not that much effort to run and it provides a ton of useful information so it’s pretty much a no brainer.

 
All in all I wanted to say thanks a lot for taking the time to visit and hopefully you can make use of the Powershell script in your environment. If you like these kinds of posts, feel free to check out our gallery full of useful real-world scripts. Don’t forget to check out our Youtube Page for sysadmin video content.

Post Updated: August 2020

Paul

Hi, my name is Paul and I am a Sysadmin who enjoys working on various technologies from Microsoft, VMWare, Cisco and many others. Join me as I document my trials and tribulations of the daily grind of System Administration.