[PowerShell][Example][Resource] Finding File Size throughout a folder/subfolder using recursion.
Disk management, is always a fun task. Trying to find why a disk is running out of space... so whats a quick way. Copy and paste below of course. I recommend saving this into a file called "FileSize.ps1", or just download the files from here: filesize.zip.
class SizeIndex{
[float] $Size
[string] $CreationUnit
[float] $SizeInBytes
[float] $SizeInKB
[float] $SizeInMB
[float] $SizeInGB
[void] SetByte ($value) {$this.SizeInBytes = $value}
[void] SetKB ($value) {$this.SizeInKB = $value}
[void] SetMB ($value) {$this.SizeInMB = $value}
[void] SetGB ($value) {$this.SizeInGB = $value}
[void] set([float]$size, [string] $unit) {
$byte = 0;
switch($unit){
"Byte" {$byte = $size}
"B" {$byte = $size}
"KiloByte" {$byte = $size/1000}
"KB" {$byte = $size/1000}
"MegaByte" {$byte = $size/1000000}
"MB" {$byte = $size/1000000}
"GigaByte" {$byte = $size/1000000000}
"GB" {$byte = $size/1000000000}
}
$this.SetByte($byte)
$this.SetKB($byte/1000)
$this.SetMB($byte/1000000)
$this.SetGB($byte/1000000000)
}
}
$script:fileCount = 0
function Get-DirectorySize{
[cmdletbinding()]
param(
[string] $Path,
[Validateset("Byte","KiloByte","MegaByte", "GigaByte")]
[string] $Unit,
[bool] $Recurse = $false,
[bool] $OutFile = $false,
[string] $OutputFileName = "$((Get-Item -Path ".\" -Verbose).FullName)\DirectoryScanOutput.csv"
)
$directoryFiles = gci $Path
foreach($directoryFile in $directoryFiles){
if($directoryFile.attributes -eq "Directory"){
if($recurse){
get-directorySize -path $($directoryFile.FullName) -unit $Unit -recurse $Recurse -outfile $outfile -outputfilename $outputFileName
}
}else{
$sizeIndex = [SizeIndex]::new()
$sizeIndex.set($directoryFile.Length, "Byte")
$directoryFile | Add-Member -MemberType NoteProperty -Name Unit -Value $Unit
switch($unit){
"Byte" {$directoryFile | Add-Member -MemberType NoteProperty -Name Size -Value $sizeIndex.SizeInBytes}
"KiloByte" {$directoryFile | Add-Member -MemberType NoteProperty -Name Size -Value $sizeIndex.SizeInKB}
"MegaByte" {$directoryFile | Add-Member -MemberType NoteProperty -Name Size -Value $sizeIndex.SizeInMB}
"GigaByte" {$directoryFile | Add-Member -MemberType NoteProperty -Name Size -Value $sizeIndex.SizeInGB}
}
$outputString = "$($directoryFile.Name); $($directoryFile.BaseName); $($directoryFile.Extension); $($directoryFile.Size); $($directoryFile.Unit); $($directoryFile.Directory)"
Write-Verbose $outputString
if($OutFile){
$outputString | Out-file $OutputFileName -Append
}
$script:fileCount++
}
}
}
And then the usage:
. .\FileSize.ps1
$startTime = Get-Date
Get-DirectorySize -Path "C:\Users\rober\desktop" -Unit "MegaByte" -Recurse $true -OutFile $true -OutputFileName "C:\Users\rober\Desktop\PS Projects\DirectoryData.csv" -verbose
$endTime = Get-Date
$timeSpan = $endTime - $startTime
"File Count: $script:fileCount"
"StartTime: $startTime EndDate: $endTime RunTimeInMinutes: $($timeSpan.TotalMinutes)"
This will generate a file where you tell it to, and it will be seperated via semicolon (;). Use excel, hit the data tab, text to columns and poof you can sort add it up.. your call.
For those of you curious on whats going on... I created a class to handle different file sizes. By defualt, Get-ChildItem (GCI) gets size in bytes, but I created this class to force data to byte and then you can get whichever unit you'd like.
I perform the GCI and if recursion is set to true, if a directory is found (via the attributes of the file) we call the function with the new path, passing the current directory. This will continue until a folder had no directories, gets any file info then work its way back upwards until hitting the root folder that you specified in the first place... you know recursion. :)
This will allow you to output to a file or just use the -verbose flag (thanks to commandletbindings) to print it on screen (of course you can always do both).
To give you some expectation of how long this will run... I used the above example and here's the output [27k files in ~ 1 min]:
File Count: 27790
StartTime: 09/07/2017 23:49:39 EndDate: 09/07/2017 23:50:53 RunTimeInMinutes: 1.235082045
Happy Scripting!