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.

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

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.

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