PowerShell : Get Folder Size on Disk, One-Line Command

I mentioned in the last part that you should be able to get the sizes of sub-folders within a folder with Measure-Object and Group-Object.  So I had a bit of a tinker as an intellectual exercise and I worked up a one-liner that works.  Ish.  As I mentioned previously, this won’t automatically add the size of each sub-folder to the parent folder (so in the results you’d get C:\Source as 10 KB and C:\Source\Sub as 100 MB, for example).

Still, it was pretty interesting to hack it together.  The command and a brief explanation follows.

GCI C:\source -recurse | Group-Object -Property Directory |
 % {New-Object PSObject -Property @{Name=$_.Name;Size=($_.Group |
 ? {!($_.PSIsContainer)} | Measure-Object Length -sum).Sum}} |
 Sort-Object -Property Size -Descending

Nice and clear 🙂  Here’s a breakdown;

GCI C:\source -recurse |

GCI is the alias to Get-ChildItem which gets all the children of an object. In this case we’re using the folder C:\Source. The -recurse switch makes it navigate down whichever tree-structure it’s using, in this case the sub-folders within the folder.  The output is sent onto the next command via the pipeline (|).

Group-Object -Property Directory |

Group all the items by the Directory property. So this groups all the items within a folder or sub-folder and pipes the output onwards.

% {New-Object PSObject -Property @{Name=$_.Name;Size=($_.Group |
 ? {!($_.PSIsContainer)} |

The next stage in the pipeline is a bit more complicated;

% is the PowerShell alias for For-Each.  So the command in the following curly braces {} is executed for each object that is passed from the pipeline.

New-Object PSObject -Property @{} creates a new PSObject with properties defined by the hash-table passed as a parameter (bounded by @{}).

Name=$_.Name; defines the first property.  It’s called Name and its value is set to the same as the Name property of the object currently being processed by the pipeline (represented by $_).

Size=($_.Group | ? {!($_.PSIsContainer).  The second property in PSObject we’re creating is called Size.  We want all the items defined in the group but we filter (using ?, an alias to PowerShell’s Where-Object command) to only items that aren’t folders (as folders have no length attribute and therefore no size).  ! is the alias to -not in PowerShell.

| Measure-Object Length -sum).Sum}} |

We then take all the items in a group which aren’t folders and sum them with Measure-Object.  This returns an object with multiple fields but we’re only interested in the sum property so that’s what we return (().Sum). This finishes creating the PSObject with Name and Size properties and we then pass this new object onto the next stage of the pipeline.

Sort-Object -Property Size -Descending

We then sort these objects by their size in descending order.

Run the command and the results are as below;

Folder Size Results

2 thoughts on “PowerShell : Get Folder Size on Disk, One-Line Command”

  1. Meanwhile, in the Unix world,
    du | sort -n
    Has been doing a similar trick for the last 30 years. Though I prefer
    du –max-depth=1 | sort -n
    du -sh
    Now which is more typeable?
    Of course, if you want something equally arcane, there’s a perl script for that too 🙂

  2. Does that include file listings / hidden files? The normal UNIX command to get those I use is a little bigger.

    The advantage to the PowerShell is that it returns a set of objects rather than text so any further work I want to do is easy. So I could list all the members of all the groups that have audit permission on the files with “*.doc” extension (for example) with only a line or two more.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s