Using PoSH to get Folder Size
I don't know about you, but there are time when I am trying to track down where all my hard drive space is going. When your system has User Account Control (UAC) enabled, right clicking on a folder to get the properties may not always show the right size.
I turn to PowerShell for a solution.
Start off by launching PowerShell as Administrator
Then change to the directory that contains the folder you want to see the size of, for example, c:\users and run the dir . cmdlet
To determine a folder size, we need to recursively query the folder for all the items in the folder and add up their file size. With the dir (get-childItem) cmdlet, the "length" property is the file size.
We can see this from running
dir .\Administrator -r
In this case, I have 4 files that have a "length", now I want to "measure" the size of each one of these items in my folder. We can pipe our results to the Measure-Object cmdlet that allows us to sum the length property
dir .\Administrator -r | Measure-Object -Property Length -Sum
We are telling Measure-object to Sum the length property on all the items below .\Administrator. We can see there are 4 files that have a total size of 1942 bytes
Most of the time, reading size values in bytes is not incredibly useful, so let's change it to MB. We start by just extracting the sum value by piping the results to select-object
dir .\Administrator -r | Measure-Object -Property Length -Sum | select -ExpandProperty Sum
This provides us with just the value from the measure-object cmdlet. Now you can divide this twice by 1024. The first time to change the format to kilobytes, the second time to megabytes. (Additions in "red")
((dir .\Administrator -r | Measure-Object -Property Length -Sum | select -ExpandProperty Sum)/1024/1024)
Now we have a way to measure the size of a single folder. But I want to know what the size is of each folder in c:\users. This could be pretty tedious if you have lots of profiles on a system. So let's think about how we can do this.
First, I would want to list all the directories/folders that are at the root of c:\users. If we look at all the properties that are available using Get-ChildItem (dir) by using dir | gm, we can see there is a property called PSIsContainer. If this value it true, than the item is a directory, if it's false, it’s a file. Now we can use our Get-ChildItem (dir) cmdlet and pipe the results to where-object cmdlet to filter our results to only show directories
dir . | where-object {$_.PSIsContainer -eq $True}
Next, we want to measure to size of each one of these folders, so we will need a ForEach (%) loop to measure each directory. The command might looks something like this:
dir . | where-object {$_.PSIsContainer -eq $True} | % {((dir $_ -r | Measure-Object -Property Length -Sum | select -ExpandProperty Sum)/1024/1024)}
Notice that we have combined out first command to measure a single directory with our second command that returns all directories in the current directory. This allows us to measure all the "sub folders"
So now we have results. We see that one folder had no files to measure so it threw an error and the list is a little hard to look at. You have to line up each entry with the results from your "dir . | where-object {$_.PSIsContainer -eq $True}" command.
Maybe we can improve the results a bit. Let's first start with using some .Net code to force our value into a decimal with 2 digits. To do this, we are going to add this code to convert our value, "{0:n2}" -f
dir . | where-object {$_.PSIsContainer -eq $True} | % {"{0:n2}" -f ((dir $_ -r | Measure-Object -Property Length -Sum | select -ExpandProperty Sum)/1024/1024)}
(for more information on formatting numbers, see: https://technet.microsoft.com/en-us/library/ee692795.aspx)
Using this formatting technique we see that all of our folders have less than 0.00 MB in them.
So let's move to a different directory like "Program Files" and get some better results.
Now the data looks better, however, it's still hard to determine which folder is which size. Here we can use a PowerShell Hash Table to help out. Let's define an empty Hash Table
$FolderSize = @{}
Next, we need to modify our command a little more to add data to this table instead of printing it to the screen.
dir . | where-object {$_.PSIsContainer -eq $True} | % {$FolderSize.Add($_.FullName, "{0:n2}" -f ((dir $_ -r | Measure-Object -Property Length -Sum | select -ExpandProperty Sum)/1024/1024))}
We can now look at the data stored in our $FolderSize hash table and since it's an object, we can manipulate it like other object (such as format-list (fl)). It makes it easy to now line up the directory and the size of the directory.
So let's bring is all together.
First we create a empty Hash table. Second we measure all the sub-directories that exists in the current directory and put them into the has table. Finally we view the hash table.
$FolderSize = @{}
dir . | where-object {$_.PSIsContainer -eq $True} | % {$FolderSize.Add($_.FullName, "{0:n2}" -f ((dir $_ -r | Measure-Object -Property Length -Sum | select -ExpandProperty Sum)/1024/1024))}
$FolderSize
Alternatively, there is a great tool in the Sysinternals Suite called du.exe that works well.