Use this convertbytes2human function, If you want to convert a number of bytes (for example 43252) or an exponential number number of bytes (such as 1.03e5) to a human readable size. NOTE: since bytes are the universal number we convert from bytes and not from anything else. Also we convert here to KiB and MiB (base 2 numbers, so 1 KiB is 1024 bytes and 1 MiB is 1024*1024 bytes)

Also I have another similar article: Converting with BASH

# CONVERT BYTES TO HUMAN WITH AWK
# convert from bytes number to human readable, example input "convertbytes2human 2345" or "convertbytes2human 1.324e5"
# got script from here (comment 11): http://www.linuxquestions.org/questions/programming-9/gawk-awk-tcsh-how-to-convert-large-number-to-human-readable-mb-gb-etc-597921/
# I added sign (old script would stall is had - sign)
# fixed error in script it used ** now we use ^
# also fixed error where 0 gave nan, it just need to give 0
convertbytes2human () {
 echo $1 | awk '{xin=$1;if(xin==0){print "0 B";}else{x=(xin<0?-xin:xin);s=(xin<0?-1:1);split("B KiB MiB GiB TiB PiB",type);for(i=5;y < 1;i--){y=x/(2^(10*i));}print y*s " " type[i+2];};}'
}

If you want to see the awk script formatted nicely, here you go. First it just checks if the input (which we call xin) is 0 or else we get the nan error (its a hack). Then if the input (xin) is not 0 we do the calculation. First in the calculation we get the absolute value (using trick mentioned at the bottom), then we save the sign using the variable s (which is either -1 or 1 for the sign of the original input number). (we return the sign later by multiplying the answer which is y by s). We do that absolute value & sign trick so that we can have negative inputs, without that part (so just like you see in the url given – original script from url at the very bottom if you want to see it, its from comment 11 in the link, the script would get stuck). After that the script works its way down to a human readable number, until it reaches, y the final answer.

'{
  xin=$1;
  if(xin==0) {
    print "0 B";
  } else {
    x=(xin<0?-xin:xin);
    s=(xin<0?-1:1);
    split("B KiB MiB GiB TiB PiB",type);
    for(i=5;y < 1;i--) {
      y=x/(2^(10*i));
    }
    print y*s " " type[i+2];
  };
}'

Note that x=(xin<0?-xin:xin);  Is the same as x=abs(xin)

Original script from comment 11 in the url listed (had to remove the BEGIN so that we can feed it an input of $1)

#!/usr/bin/awk -f

BEGIN{	x = 456456

        split("B KB MB GB TB PB",type)

	for(i=5;y < 1;i--)
	    y = x / (2**(10*i))

	print y type[i+2]
}

 

2 thoughts on “AWK – convert BYTES to HUMAN READABLE

  1. Another AWK snippet with example

    Another awk snippet that does the same thing (courtesy of http://unix.stackexchange.com/questions/44040/a-standard-tool-to-convert-a-byte-count-into-human-kib-mib-etc-like-du-ls1#):

    echo 23423423 | awk 'function human(x) { s=" B KiB MiB GiB TiB EiB PiB YiB ZiB"; while (x>=1024 && length(s)>1) {x/=1024; s=substr(s,5)} s=substr(s,1,4); xf=(s==" B ")?"%5d ":"%8.2f"; return sprintf( xf"%s\n", x, s); } {gsub(/^[0-9]+/, human($1)); print}'

    Example: use it in a script to get size of all drives (sd and hd drives)

    $ for i in `cat /proc/partitions | egrep "sd|hd" | grep -v "[0-9]$" | awk '{print $4}'`; do echo "$i: `blockdev --getsize64 /dev/$i` bytes, `blockdev --getsize64 /dev/$i | awk 'function human(x) { s=" B KiB MiB GiB TiB EiB PiB YiB ZiB"
    ; while (x>=1024 && length(s)>1) {x/=1024; s=substr(s,5)} s=substr(s,1,4); xf=(s==" B ")?"%5d ":"%8.2f"; return sprintf( xf"%s\n", x, s); } {gsub(/^[0-9]+/, human($1)); print}'`"; done;

    sdc: 2000398934016 bytes, 1.82 TiB
    sdd: 2000398934016 bytes, 1.82 TiB
    sde: 250306560 bytes, 238.71 MiB
    sdf: 2000398934016 bytes, 1.82 TiB
    sdg: 2000398934016 bytes, 1.82 TiB
    sdb: 8001563221504 bytes, 7.28 TiB
    sda: 2000398934016 bytes, 1.82 TiB

Leave a Reply

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