Linux – Output Disk Size in GB Without Rounding Error

bashhard drivelinuxpartitioningUbuntu

Output disk size in GB only. Giga Bytes only.
Not MB. Not Mega Bytes.
Not TB. Not Tera Bytes.

Tested thus far:

sudo blockdev --getsize64 /dev/sda
1000204886016

sudo blockdev --getsize64 /dev/sda |bc -l |awk '{print $1/1000000000}'
1000.2

sudo blockdev --getsize64 /dev/sda |bc -l |awk '{print $1/1000000000}' |numfmt --field=1- --format=%.0f --invalid=ignore
1001

But above 1001 output is a rounding error.
1000 is ideal output, meaning 1000 GB disk size.

Question1:
How to fix above rounding error?

Question2:
What is a more elegant way or shorter way versus 120 characters below:
sudo blockdev --getsize64 /dev/sda |bc -l |awk '{print $1/1000000000}' |numfmt --field=1- --format=%.0f --invalid=ignore

.
.

using:
neofetch --stdout |grep 'OS:'

OS: Kubuntu 22.04.3 LTS x86_64

Best Answer

Strictly speaking it's not a rounding error under the rounding method used by numfmt, of which there are several. You need to choose the rounding behavior you want, likely --round=nearest for the one most people expect:

   --round=METHOD
          use METHOD for rounding when scaling; METHOD can be: up,
          down, from-zero (default), towards-zero, nearest

But as you only want a specific unit (GB), numfmt is completely redundant here after you've already done the division using awk – all it does for you is add the 'G', and you can already do that from awk itself, as well as use awk's own float (or even integer) formatting where %.0f always uses nearest rounding (and %d truncates).

$ blockdev --getsize64 /dev/sda | awk '{printf("%.0f GB\n", $1/1000000000)}'
1000 GB

The bc -l appears to be redundant in your example since you're not actually doing any operations within 'bc', but you could use it as well:

$ sz=$(blockdev --getsize64 /dev/sda); echo "$sz/1000000000" | bc

You can also use Bash's integer arithmetic within $(( ... )) or $[...] (identical but the latter is non­standard) if truncation (rounding down) is good enough:

$ sz=$(blockdev --getsize64 /dev/sda); echo "$[sz/1000000000]G"
Related Question