9

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

4.9/5 - (16 votes)

Paul Contreras

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.

9 Comments

  1. Hi Paul,
    This script doesn’t do anything. It instantly returns to the command prompt and nothing else is returned. Does it require a specific version of Powershell?
    Thanks, JIm

  2. Hi Paul, what can I do to prevent my folder paths (those beyond the directory I provide) from truncating with a …?

    • Hi – There are several options so it doesn’t truncate. Any of the below will do.

      – Output to csv
      – Store the output as a variable
      – Pipe the command to format-list

  3. This is fantastic! I’m using it for a home folder migration project in which we hope to reduce the amount of on-premise file storage allocated to users. It has been very helpful in finding the users who are the biggest hoarders.

  4. Thanks for the great article.
    I see the recursive mode that lists all the subfolders.
    Is there a way to just list the first level of folders and not list all of the recursive folders but still have the total size and file count for each?
    Meaning if I have a folder with 8 subfolders and each of those subfolders has subfolders, I only want output that lists the 8 folders–each of the eight rows with the aggregate number of files and size.
    Thank you again!

  5. First of all Thank you very much for this is wonderful script. I would like to ask, how I can convert this script to gather information from remote computers ?? for example, I want to get the size of the directories from multiple remote computers and display exact same output in html view?

  6. How Can i export it to txt or cvs? Tried to put the output before the End and couldn’t get it done with the MBSize

  7. Thought perhaps your script could halp in my finding Directories within Directories SharePoint and OneDrive Biz and OneDrive Personal.
    I am so confused and my harddrive, Directories and Clouds are a total mess
    I have OneDrive within OneDrive itself!!
    If I get this cleaned up it may only happen all over again if I do not determine how this occurred.
    I think I am going to need to search Folder Structure first because viewing all Folders and Files is confusing – too much info with having so many duplications
    Do you help others automate? triggers notifications flows scripts ?

Leave a Reply

Your email address will not be published. Required fields are marked *