≡ Menu

Convert from any-to-any (Bytes, KB, MB, GB, TB) using PowerShell

We all know that size conversion in PowerShell is pretty straightforward. If you have a number in bytes and want to convert it into MB or GB, it is as simple as typing 12345/1GB or 12345/1MB in PowerShell prompt or script.

Ok, then where is the problem and why I am writing this post. The real problem comes in two scenarios.

Scenario#1

When you want to convert a value from other than bytes to KB/MB/TB/GB: It is easy to convert any format to other using PowerShell console but when it comes to writing scripts, we will have this problem. For example, VMware datastores will have a property which says CapacityinMB and the value will be integer. In that case, you need to convert the number to bytes and then convert back to your final required format. This is because, from property name you know it is in MB but there is no easy way to make the shell understand that is in MB while doing the conversion. Conversion like 245760/1GB treats 245760 as bytes and calculation will go wrong. We can follow a ugly way like suffixing the number with a string “MB” and then divide it by 1GB (“245760MB”/1GB). I feel this not a good programming approach.

powershell-size conversion 1

Scenario#2

When want to apply precision and return only 2(or any given number) of digits after the dot: Another problem you will notice is the no. of digits you want to have in the precision numbers. When converting using the traditional method, we will end up with more number of precision digits which I want to avoid. I just need 2 or 3 based on my requirement. Again we can address this by using a ugly method by calling Tostring(“00”)

powershell-precision-1

To address above two scenarios, I came with below function which eases the conversion from any-to-any (Bytes, KB, MB, GB, and TB). It also has a facility mention the no. of precision digits you want to have.

Code#

function Convert-Size {            
[cmdletbinding()]            
param(            
    [validateset("Bytes","KB","MB","GB","TB")]            
    [string]$From,            
    [validateset("Bytes","KB","MB","GB","TB")]            
    [string]$To,            
    [Parameter(Mandatory=$true)]            
    [double]$Value,            
    [int]$Precision = 4            
)            
switch($From) {            
    "Bytes" {$value = $Value }            
    "KB" {$value = $Value * 1024 }            
    "MB" {$value = $Value * 1024 * 1024}            
    "GB" {$value = $Value * 1024 * 1024 * 1024}            
    "TB" {$value = $Value * 1024 * 1024 * 1024 * 1024}            
}            
            
switch ($To) {            
    "Bytes" {return $value}            
    "KB" {$Value = $Value/1KB}            
    "MB" {$Value = $Value/1MB}            
    "GB" {$Value = $Value/1GB}            
    "TB" {$Value = $Value/1TB}            
            
}            
            
return [Math]::Round($value,$Precision,[MidPointRounding]::AwayFromZero)            
            
}            
            

Output:

The output is very intuitive and explains the usage.

convert-size-output

Hope this helps…

{ 11 comments… add one }
  • Ujjval Parnandi December 10, 2014, 2:45 pm

    Thanks Sitaram, that was very helpful.

  • Robert February 9, 2016, 12:30 am

    Actually, all of that is unfortunately wrong. From Powershell’s conversion ( x / 1 GB ) to the script you wrote. And that is because of the industry’s changes to naming conventions (http://physics.nist.gov/cuu/Units/binary.html). GB = * 1000^3 & GiB = * 1024^3

    You should augment your script to handle both.

    A second suggestion, instead of using Byte, use both B and b (for Byte and bit – to maintain conformity).

    I look forward to the update. Thnx.

  • Void December 10, 2016, 1:56 am

    Here’s a slight update to the script that handles both binary, and historical data size prefixes. Some formatting may get altered in the copy/paste; however, it should still work.

    Thanks for posting the original script/function.

    —– Revised Code below this line —-

    [cmdletbinding()]
    param(
    [validateset(“b”, “B”,”KB”,”KiB”,”MB”,”MiB”,”GB”,”GiB”,”TB”,”TiB”,”PB”,”PiB”,”EB”,”EiB”, “ZB”, “ZiB”, “YB”, “YiB”)]
    [Parameter(Mandatory=$true)]
    [string]$From,
    [validateset(“b”, “B”,”KB”,”KiB”,”MB”,”MiB”,”GB”,”GiB”,”TB”,”TiB”,”PB”,”PiB”,”EB”,”EiB”, “ZB”, “ZiB”, “YB”, “YiB”)]
    [Parameter(Mandatory=$true)]
    [string]$To,
    [Parameter(Mandatory=$true)]
    [double]$Value,
    [int]$Precision = 4
    )

    # Convert the supplied value to Bytes
    switch -casesensitive ($From) {
    “b” {$value = $value/8 }
    “B” {$value = $Value }
    “KB” {$value = $Value * 1000 }
    “KiB” {$value = $value * 1024 }
    “MB” {$value = $Value * 1000000 }
    “MiB” {$value = $value * 1048576 }
    “GB” {$value = $Value * 1000000000 }
    “GiB” {$value = $value * 1073741824 }
    “TB” {$value = $Value * 1000000000000 }
    “TiB” {$value = $value * 1099511627776 }
    “PB” {$value = $value * 1000000000000000 }
    “PiB” {$value = $value * 1125899906842624 }
    “EB” {$value = $value * 1000000000000000000 }
    “EiB” {$value = $value * 1152921504606850000 }
    “ZB” {$value = $value * 1000000000000000000000 }
    “ZiB” {$value = $value * 1180591620717410000000 }
    “YB” {$value = $value * 1000000000000000000000000 }
    “YiB” {$value = $value * 1208925819614630000000000 }
    }

    # Convert the number of Bytes to the desired output
    switch -casesensitive ($To) {
    “b” {$value = $value * 8}
    “B” {return $value }
    “KB” {$Value = $Value/1000 }
    “KiB” {$value = $value/1024 }
    “MB” {$Value = $Value/1000000 }
    “MiB” {$Value = $Value/1048576 }
    “GB” {$Value = $Value/1000000000 }
    “GiB” {$Value = $Value/1073741824 }
    “TB” {$Value = $Value/1000000000000 }
    “TiB” {$Value = $Value/1099511627776 }
    “PB” {$Value = $Value/1000000000000000 }
    “PiB” {$Value = $Value/1125899906842624 }
    “EB” {$Value = $Value/1000000000000000000 }
    “EiB” {$Value = $Value/1152921504606850000 }
    “ZB” {$value = $value/1000000000000000000000 }
    “ZiB” {$value = $value/1180591620717410000000 }
    “YB” {$value = $value/1000000000000000000000000 }
    “YiB” {$value = $value/1208925819614630000000000 }
    }

    return [Math]::Round($value,$Precision,[MidPointRounding]::AwayFromZero)

  • Void December 10, 2016, 1:58 am

    And of course it stripped out the header information. Ad the following if you care in between the normal powershell script header notation.

    —- Header Info Below —-
    .SYNOPSIS
    This powershell script converts computer data sizes between one format and another.
    Optionally you can specify the precision and return only 2 (or any given
    number) of digits after the decimal.

    .DESCRIPTION
    Size conversion in PowerShell is pretty starightforward. If you have a number in
    bytes and want to convert it into MB, or GB, it is as simple as typing 12345/1GB, or
    12345/1MB in PowerShell prompt or script.

    The problem comes when you want to convert a value from something other than bytes to
    something else, and being able to properly handle either base 10 (KB, MB, GB, etc.),
    or base 2 (KiB, MiB, GiB, etc.) size notations correctly.

    Another issue is that you may want to be able to control the precision of the returned
    result (e.g. 0.95 instead of 0.957870483398438).

    This script easily handles conversion from any-to-any (e.g. Bits, Bytes, KB, KiB, MB,
    MiB, etc.) It also has the ability to specify the precision of digits you want to
    recieve as the output.

    International System of Units (SI) Binary and Standard
    http://physics.nist.gov/cuu/Units/binary.html
    https://en.wikipedia.org/wiki/Binary_prefix

    Name Symbol Value Unit Notation English Word
    ——– —— ——————————— —– ——– ————
    Bit (b) : 1 bit
    Bytes (B) : 8 bits ( 2^3 )
    KiloByte (KB) : 1 000 Bytes (10^3 ) Thousand
    KibiByte (KiB): 1 024 Bytes ( 2^10)
    MegaByte (MB) : 1 000 000 Bytes (10^6 ) Million
    MebiByte (MiB): 1 048 576 Bytes ( 2^20)
    GigaByte (GB) : 1 000 000 000 Bytes (10^9 ) Billion
    GibiByte (GiB): 1 073 741 824 Bytes ( 2^30)
    TeraByte (TB) : 1 000 000 000 000 Bytes (10^12) Trillion
    TebiByte (TiB): 1 099 511 627 776 Bytes ( 2^40)
    PetaByte (PB) : 1 000 000 000 000 000 Bytes (10^15) Quadrillion
    PebiByte (PiB): 1 125 899 906 842 624 Bytes ( 2^50)
    ExaByte (EB) : 1 000 000 000 000 000 000 Bytes (10^18) Quintillion
    ExbiByte (EiB): 1 152 921 504 606 850 000 Bytes ( 2^60)
    ZettaByte (ZB) : 1 000 000 000 000 000 000 000 Bytes (10^21) Sextillion
    ZebiByte (ZiB): 1 180 591 620 717 410 000 000 Bytes ( 2^70)
    YottaByte (YB) : 1 000 000 000 000 000 000 000 000 Bytes (10^24) Septillion
    YobiByte (YiB): 1 208 925 819 614 630 000 000 000 Bytes ( 2^80)

    .NOTES
    File Name : Convert-Size.ps1
    Author : Techibee posted on July 7, 2014
    Modified By: Void, modified on December 9, 2016

    .LINK
    http://techibee.com/powershell/convert-from-any-to-any-bytes-kb-mb-gb-tb-using-powershell/2376

    .EXAMPLE
    Convert-Size -From KB -To GB -Value 1024
    0.001

    Convert from Kilobyte to Gigabyte (Base 10)
    .EXAMPLE
    Convert-Size -From GB -To GiB -Value 1024
    953.6743

    Convert from Gigabyte (Base 10) to GibiByte (Base 2)
    .EXAMPLE
    Convert-Size -From TB -To TiB -Value 1024 -Precision 2
    931.32

    Convert from Terabyte (Base 10) to Tebibyte (Base 2) with only 2 digits after the decimal

    • Michael January 4, 2019, 8:07 pm

      Hello,

      the script assepts wrong upper/lower-case letters and the results are false. Can you correct this?

      Cmdlet an der Befehlspipelineposition 1
      Geben Sie Werte für die folgenden Parameter an:
      From: KB
      To: kiB
      Value: 1
      1000

      Michael

      • Void November 3, 2019, 10:57 pm

        Hi Michael,

        The issue with case insensitive input parameters should be resolved. If an incorrect parameter is passed it’ll thow an error message. If I made the minimum requirement PowerShell 6 core we could more gracefully capture it with the use of the “ErrorMessage” option on the validateset; however, that option isn’t compatible with PowerShell 5.1…

        In case anyone’s interested you can find the updated script at https://github.com/void-gh/pwsh-data-size-unit-measure

  • Frederic Vets May 19, 2018, 9:59 pm

    Hi,

    If you’ve landed on this page, you might be interested in a PowerShell module I wrote. It contains several handy cmdLets related to this topic.

    Get-Size : itterate through a directory and return the total size (in bytes).
    Convert-Size : converts a size from one unit to another. E.g. x KiB (kibibytes) -> y MB (megabytes)
    Get-SizeConverted : Combination of the 2 above. Supports the -ShowOnlyRelevant switch, to automatically pick the most meaningful unit for that specific size.

    You’ll find it at : https://github.com/FredericVets/PowershellPlayground

    Frederic.

  • Michael January 4, 2019, 7:43 pm

    Hello,

    the script assepts wrong upper/lower-case letters and the results are false. Can you correct this?

    Cmdlet an der Befehlspipelineposition 1
    Geben Sie Werte für die folgenden Parameter an:
    From: KB
    To: kiB
    Value: 1
    1000

    Michael

  • GWCN January 12, 2019, 12:48 am

    There are far easier ways to do this stuff.

Leave a Comment