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.
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”)
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.
Hope this helps…
Comments on this entry are closed.
Thanks Sitaram, that was very helpful.
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.
OK, Robert, YOU go tell the folks at Microsoft to change their naming conventions. In the meantime, we gotta work with what we have, and if MS says 1 KB = 1024 bytes, etc., then that’s what the nomenclature I’m using in my scripts. We aren’t writing scientific papers here – we’re coding.
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)
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
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
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
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.
Thanks for sharing.
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
There are far easier ways to do this stuff.
Yes agree. Do you want to share it with us?
Thanks a lot !!!!!Solved my problem:)
Is it possible to see the output as a percentage
Do you have a sample output that you are looking for?