A reusable PowerShell function to select the correct size format

Recently I’ve been asked several times to write a script to create a report about storage usage… going from simple file sizes and directory sizes to storage utilization within virtual machines. Every single time I got to the point where I needed to decide on the output… in MB? GB? Or just plain bytes?
This is not a proper way to do this… to do it right, the script would need to look at the size of the object and decide per object what size format it should use Glimlach 

Now, here’s a handy reusable function that takes the size (or ‘length’ as the size property is named) of a file as a mandatory input, calculates which size format is most appropriate and provides this as an output…

function Select-SizeFormatType
{
# Define the mandatory input parameter
param ( [Parameter(Mandatory=$true, ValueFromPipeline=$true, Position=0)][System.int64]$sizeInBytes)
switch ($SizeInBytes)
{
# Determine the correct size format and use ‘break’ to exit the switch
{$SizeInBytes -ge 1TB} {“{0:n$sigDigits}” -f ($SizeInBytes/1TB) + ” TB” ; break}
{$SizeInBytes -ge 1GB} {“{0:n$sigDigits}” -f ($SizeInBytes/1GB) + ” GB” ; break}
{$SizeInBytes -ge 1MB} {“{0:n$sigDigits}” -f ($SizeInBytes/1MB) + ” MB” ; break}
{$SizeInBytes -ge 1KB} {“{0:n$sigDigits}” -f ($SizeInBytes/1KB) + ” KB” ; break}
Default { “{0:n$sigDigits}” -f $SizeInBytes + ” Bytes” }
}
}

5 comments

  1. Very useful. Where is $sigDigits coming from? And the point of -f is that items to the right of -f are values. I would put the the KB etc on the other side: 
    “{0:n$sigDigits}KB” -f ($SizeInBytes/1KB) . It is also easy for people to forget that this formatting results in a string which potentially could mean sorting wouldn’t work the way you might expect.

  2. Jeff Wouters says:

    Hi Jeff, thanks for your good response. The $sigDigits was part of the larger script this function is a part of… changed it to $Digits to make it a bit more understandable. I didn’t knew that about -f, thanks for the clarification 🙂 Your comment about sorting with strings made me think… one could use “Sort-Object {[int] $_.SizeInBytes}” in the same way you would sort a CSV file… or am I missing the point here?

  3. In a function, everything should be self contained. If I try to run your function it will likely fail since I don’t have a definition for $Digits. Your function is referencing a variable out of scope which is not recommended. You would be better served by adding it as a parameter to your function. As for sorting you are on the right track. Although $SizeinBytes is likely already a numeric value. What you would need to recast as an int is your formatted value.  By the way, your revised version left out the comparison. This won’t work.

  4. Hmmm…I should have tested your original code. I don’t think you can use Switch this way.

  5. You got me distracted now. Here’s I might sort the results. Definitely not something I would expect someone new to PowerShell to figure out.

    PS S:> 122334,554335566,1234,889872,777622222| Select-sizeformatType | Sort @{expression={
     [double]$value=$_.Substring(0,$_.length-2)
    [string]$size=$_.Substring($_.length-2) 
    Switch ($size) {
      “PB” {$value*1PB}
      “TB” {$value*1TB}
      “GB” {$value*1GB}
      “MB” {$value*1MB}
      “KB” {$value*1KB}
      Default {$value}
     } #switch }
    } #expression

    1.21KB
    119.47KB
    869.02KB
    528.66MB
    741.60MB

Leave a Reply

Your email address will not be published. Required fields are marked *