PowerShell Treesize for Windows (Get-Treesize.ps1)

After my “treesize”-esque programs for NetApp Clustered ONTAP and 7-Mode, it occurred to me that it would be fairly trivial to write a ‘PowerShell Treesize for Windows’. Of course, this is perhaps a slightly pointless endeavour when there is already the excellent TreeSize Free from Jam-Software. One thing I should point out, is that even running in ‘Administrator: Windows PowerShell’, you still might get some access denied (which we don’t get with our NetApp Treesizes run as admin/root.)

Here is a usage example>


.\Get-Treesize.ps1 -ScanStartPath C:\Users


You want to run this in Windows PowerShell remembering to right-click the icon to ‘Run as administrator’.

Image: Running PowerShell Treesize for Windows in ‘Administrator: Windows PowerShell’

And the output is a CSV file (default name = TreesizeReport.CSV, specify -OutputFile to change this name) with these columns:

Order
Directory Level
File Type
Name
Path
File Size (bytes)
Dir. Size (bytes)
Creation Time
Last Access Time
Last Write Time

Note: My personal recommendation is - don’t use this, use TreeSize Free from Jam-Software (and no, I don’t have shares.)

The Script


##################
## Get-Treesize ##
##################

Param(
  [Parameter(Mandatory=$True,HelpMessage="Example: C:\Users")]
  [String]$ScanStartPath,
  [String]$OutputFile = "TreesizeReport.CSV",
  [String]$DateFormat = "yyyy.MM.dd"
);""

## VERIFY $ScanStartPath ##
"INFO: $ScanStartPath verifying ..."
$ScanStartPath = $ScanStartPath.Trim("\")
If(!(Get-ChildItem -Path $ScanStartPath)){"ERROR: $ScanStartPath is incorrect!";EXIT}
"INFO: $ScanStartPath verified.`n"

## GLOBAL VARIABLES ##
[System.Array]$Global:CSV = @() # Output CSV
[Int64]$Global:Order = 0 # For output ordering

## ADD TO CSV FUNCTION ##
Function AddInfoToCSV{
  $Global:Order ++
  $Global:CSV += [PSCustomObject]@{
    "Order"             = $Global:Order
    "Directory Level"   = $Level
    "File Type"         = "file"
    "Name"              = $G.Name
    "Path"              = $Path
    "File Size (bytes)" = $G.Length
    "Dir. Size (bytes)" = ""
    "Creation Time"     = $G.CreationTime.ToString($DateFormat)
    "Last Access Time"  = $G.LastAccessTime.ToString($DateFormat)
    "Last Write Time"   = $G.LastWriteTime.ToString($DateFormat)
  }    
  Return $G.Length
}

## RECURSIVE SCANNING FUNCTION ##
Function GetDirInfoRecursive{
  Param([String]$Path)
  Write-Host "." -NoNewLine
 
  ## PATH MANIPULATIONS ##
  [System.Array]$PathSplit = $Path.Split("\")
  [Int]$level = $PathSplit.count
  [String]$CurrentDir = $PathSplit[$level - 1]
  [String]$SubPath = ""
  For($i = 0; $i -lt ($level -1); $i++){$SubPath += $PathSplit[$i] + "\"}         
 
  ## CHECKING CURRENT DIRECTORY ##
  $CurrDirInf = (Get-ChildItem -Path $SubPath | Where{$_.Name -eq $CurrentDir})
  If(!$CurrDirInf){$CurrDirInf = (Get-ChildItem -Path $SubPath -Hidden | Where{$_.Name -eq $CurrentDir})}
  If(!$CurrDirInf){Return 0}
 
  ## GETTING FILES AND DIRECTORIES ##
  $GetFiles       = Get-ChildItem -Path $Path -File
  $GetHiddenFiles = Get-ChildItem -Path $Path -File -Hidden
  $GetDirectories = Get-ChildItem -Path $Path -Directory
  $GetHiddenDirs  = Get-ChildItem -Path $Path -Directory -Hidden
 
  ## ORDER AND INITIALIZE DIRSIZE ##
  $Global:Order ++
  $Local:Order = $Global:Order
  $Local:DirSize = 0
 
  ## CYCLE THROUGH DIRECTORIES AND FILES ##
  Foreach($G in $GetDirectories){$Local:DirSize += (GetDirInfoRecursive ($Path + "\" + $G.Name))}
  Foreach($G in $GetHiddenDirs) {$Local:DirSize += (GetDirInfoRecursive ($Path + "\" + $G.Name))}
  Foreach($G in $GetFiles)      {$Local:DirSize += (AddInfoToCSV $G) }
  Foreach($G in $GetHiddenFiles){$Local:DirSize += (AddInfoToCSV $G) }
 
  ## ADD DIRECTORY INFORMATION TO CSV ##
  $Global:CSV += [PSCustomObject]@{
    "Order"             = $Local:Order
    "Directory Level"   = $Level
    "File Type"         = "directory"
    "Name"              = $CurrentDir
    "Path"              = $Path
    "File Size (bytes)" = ""
    "Dir. Size (bytes)" = $Local:DirSize
    "Creation Time"     = $CurrDirInf.CreationTime.ToString($DateFormat)
    "Last Access Time"  = $CurrDirInf.LastAccessTime.ToString($DateFormat)
    "Last Write Time"   = $CurrDirInf.LastWriteTime.ToString($DateFormat) 
  }
  Return $Local:DirSize
}

##################
## MAIN PROGRAM ##
##################

("START: " + [String](Get-Date))
[Void](GetDirInfoRecursive $ScanStartPath);""
("END: " + [String](Get-Date) + "`n")
$Global:CSV | Sort "Order" | Export-CSV "$OutputFile" -NoTypeInformation


Comments