I have this Function that takes a path input, and gives you the size of it. There are 3 different options you can choose from which are:
- 'GCI' -
Get-ChildItem
- 'DIR' - CMD's DIR command
- 'ROBO' - Robocopy.exe
GCI, and DIR are identical almost everytime but, ROBO (Robocopy.exe) is so inconsistent on how it calculates different directories.
Function Get-DirectorySize {
Param (
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({Test-Path -Path $_})]
[Alias('Location')]
[String[]]$FilePath,
[Parameter(Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[ValidateSet('GCI','DIR','ROBO')]
[String]$Option
)
Process {
Foreach ($Path in $FilePath) {
Try {
if ($PSBoundParameters.ContainsKey('Option')) {
if ($PSBoundParameters.ContainsValue('GCI')){
$Start_Time = Get-Date -Format G
$File_Count = (Get-ChildItem $Path -Recurse -force -erroraction SilentlyContinue | Measure-Object length -Sum).sum
}
elseif ($PSBoundParameters.ContainsValue('DIR')) {
$Start_Time = Get-Date -Format G
$File_Count = ((cmd /c dir $Path /-C /S /A:-D-L)[-2] -split '\s+')[3]
}
elseif ($PSBoundParameters.ContainsValue('ROBO')){
$Start_Time = Get-Date -Format G
$File_Count = (robocopy.exe $Path C:\FakePath /L /XJ /R:2 /W:1 /NP /E /BYTES /NFL /NDL /NJH /J /MT:128)[-4] -replace '\D+(\d+).*','$1'
}
}
else {
$Start_Time = Get-Date -Format G
$File_Count = (Get-ChildItem $Path -Recurse -Force -ErrorAction SilentlyContinue | Measure-Object length -Sum).sum
}
}
Catch {
$Error[0].Exception.Message.Split('.')[1].Trim()
}
Finally {
[PSCustomObject]@{
'File Path' = $Path
'File Size' = Get-Size -ProcessBytes $File_Count
'Start Time' = $Start_Time
'End Time' = Get-Date -Format G
}
}
}
}
}
This is the output of some of the Directories I tested:
PS C:\WINDOWS\system32> Get-DirectorySize -FilePath C:\ -Option GCI
File Path File Size Start Time End Time
--------- --------- ---------- --------
C:\ 210.84 GB 6/26/2021 5:29:58 PM 6/26/2021 5:30:39 PM
PS C:\WINDOWS\system32> Get-DirectorySize -FilePath C:\ -Option DIR
File Path File Size Start Time End Time
--------- --------- ---------- --------
C:\ 210.84 GB 6/26/2021 5:30:42 PM 6/26/2021 5:31:00 PM
PS C:\WINDOWS\system32> Get-DirectorySize -FilePath C:\ -Option ROBO
File Path File Size Start Time End Time
--------- --------- ---------- --------
C:\ 213.24 GB 6/26/2021 5:31:06 PM 6/26/2021 5:31:11 PM
PS C:\WINDOWS\system32> Get-DirectorySize -FilePath C:\Users -Option GCI
File Path File Size Start Time End Time
--------- --------- ---------- --------
C:\Users 137.63 GB 6/26/2021 5:31:21 PM 6/26/2021 5:31:27 PM
PS C:\WINDOWS\system32> Get-DirectorySize -FilePath C:\Users -Option DIR
File Path File Size Start Time End Time
--------- --------- ---------- --------
C:\Users 137.63 GB 6/26/2021 5:31:35 PM 6/26/2021 5:31:37 PM
PS C:\WINDOWS\system32> Get-DirectorySize -FilePath C:\Users -Option ROBO
File Path File Size Start Time End Time
--------- --------- ---------- --------
C:\Users 133.21 GB 6/26/2021 5:31:41 PM 6/26/2021 5:31:41 PM
Am I in the wrong here on how I am calculating the directory sizes?
Function Get-Size{
[CmdletBinding()]
Param(
[Parameter(Mandatory=$false,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[Int64]$ProcessBytes
)
Process{
Switch ($ProcessBytes){
{$ProcessBytes -lt 1MB} { "$([Math]::Round($ProcessBytes / 1KB, 2)) KB" }
{$ProcessBytes -ge 1MB -and $ProcessBytes -lt 1GB} { "$([Math]::Round($ProcessBytes / 1MB, 2)) MB" }
Default { "$([Math]::Round($ProcessBytes / 1GB, 2)) GB" }
}
}
}
Please Note: I am aware this isn't the purpose of Robocopy but, I find it useful how it cuts the time to a fraction of the time it would've taken GCI, or DIR to complete (due to multi-threading).