Folder Usage Function

A few days ago I went over the PowerShell oneliner from SAPIEN’s March ’09 newsletter. I suggested using it in a scriptblock to save typing. Another possibility is to turn it into a function. Even better would be a function that accepts pipelined input. This would permit me to pipe in a list of folder names and get a usage object for each one.

Function Get-FolderUsage {
    BEGIN {
        #set to Continue to enable debug messages
        $debugPreference="SilentlyContinue"
        Write-Debug ("{0} Begin" -f (Get-Date))
        }
    
    PROCESS {
        #this step is optional, but it makes it easier I think
        #to follow the code
        [string]$fldr=$_
        
        Write-Debug ("{0} Enumerating {1}" -f (Get-Date),$fldr)
        
        dir $fldr -recurse -force -ea "SilentlyContinue" | 
        Measure-Object length -sum -max -average | 
        Select-Object @{name="Folder";Expression={$fldr}},`
        @{name="Files";Expression={$_.count}},`
        @{name="Largest";Expression={"{0:F2}" -f ($_.maximum/1MB)}},`
        @{name="Average";Expression={"{0:F2}" -f ($_.average/1MB)}},`
        @{name="TotalSize";Expression={"{0:F2}" -f ($_.sum/1MB)}}
        
        } #end Process script block
 
    END {
        Write-Debug ("{0} End" -f (Get-Date))
        }
}

The function uses the BEGIN, PROCESS, and END scriptblocks. This is what allows the function to accept pipelined input. The code within the BEGIN script block executes once before any pipelined objects are processed. In this function the only thing I’m doing is writing a debug message, assuming you enable the debug pipeline. Likewise, the code in the END scriptblock executes once after every pipelined object has been processed.

The majority of the work is handled by the PROCESS scriptblock. Like any pipelined expression, $_ represents the current object in the pipeline. In order to maintain consistency with my oneliner which I pasted in, and to make it easier to follow, I’m going to define $fldr with the value from the current processed object. Remember, this will be the folder path. This replaces the Read-Host portion of my original expression.

Most of the original expression remains intact. The only changes I made were to slightly modify the property names. I found that shorter names formatted better with Format-Table and it also makes it easier to use these properties for sorting or filtering. You can still use long property names but you have to enclose the property name in quotes. My changes make it simpler, hopefully. The custom object is then written to the pipeline, once for each pipelined folder path.

With this function I can execute PowerShell expressions like these:

PS C:\> $env:temp | Get-FolderUsage

PS C:\ “c:\test”,”$env:userprofile\*documents”,”c:\scripts” | Get-FolderUsage | sort “TotalSize” -desc | Format-Table -AutoSize

Or how about this one that will enumerate all the local profile folders on your computer:

 dir (Split-Path $env:userprofile) | foreach {
    $_.fullname | Get-FolderUsage
  } | sort Files -descending |
  Format-Table Folder,Files,Largest,TotalSize -autosize

Do you see the utility?

Download this function here.