PowerShell switch block and values coded in 64 bits

79 views Asked by At

I cannot use a PowerShell Switch statement when 64 bits integers are involved.

I have the follwing PowerShell snippet :

PS D:\> cat .\dirSize.ps1
$dirName = $args[0]
$dirSize = [uint64]( ( dir "$dirName" -force -recurse | measure -property length -sum ).Sum )
switch( $dirSize ) {
    { $_ -in 1tb..1pb } { "{0:n2} TiB" -f ( $dirSize / 1tb ); break }
}

I get this error :

Cannot convert value "1099511627776" to type "System.Int32". Error: "Value was either too large or too small for an Int32."
At C:\Users\sebastien.mansfeld\psh\dirSize.ps1:4 char:4
+     { $_ -in 1tb..1pb } { "{0:n2} TiB" -f ( $dirSize / 1tb ); break }
+       ~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvalidCastIConvertible

So I tried converting the switch test line to uint64 but it does not work :

switch( $dirSize ) {
    { [uint64]$_ -in [uint64]1tb..[uint64]1pb } { "{0:n2} TiB" -f ( $dirSize / 1tb ); break }
}

I get the same error message.

I'm expecting the switch condition to work.

2

There are 2 answers

3
Santiago Squarzon On BEST ANSWER

Change your condition for something more efficient that wont throw that out of bounds error:

switch ( $dirSize ) {
    { $_ -ge 1tb -and $_ -le 1pb } {
        '{0:n2} TiB' -f ( $dirSize / 1tb ); break 
    }
}

You could also make use of PSTree Module that comes with this built-in functionality, as an example, your current code would be replaced with:

(Get-PSTree $dirName -Depth 0 -RecursiveSize -Force).GetFormattedLength()

To install it, you can:

Install-Module PSTree -Scope CurrentUser
3
sirtao On

the range(..) only works with [int32] values.

Just use

switch ( $dirSize ) {
    # less or equal 1PB or more or equale 1TB
    { (1PB -ge $_) -and (1TB -le $_) } {
        '{0:n2} TiB' -f ( $dirSize / 1TB )
        break 
    }
    # { other comparsions } { other results }
    # default { default result }
}