Tell me more ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Is there a standard tool which converts an integer count of Bytes into a human-readable count of the largest possible unit-size, while keeping the numeric value between 1.00 and 1023.99 ?

I have my own bash/awk script, but I am looking for a standard tool, which is found on many/most distros... something more generally available, and ideally has simple command line args, and/or can accept piped input.

Here are some examples of the type of output I am looking for.

    1    Byt  
  173.00 KiB  
   46.57 MiB  
    1.84 GiB  
   29.23 GiB  
  265.72 GiB  
    1.63 TiB  

Here is the bytes-human script (used for the above output)

awk -v pfix="$1" -v sfix="$2" 'BEGIN { 
      split( "Byt KiB MiB GiB TiB PiB", unit )
      uix = uct = length( unit )
      for( i=1; i<=uct; i++ ) val[i] = (2**(10*(i-1)))-1
   }{ if( int($1) == 0 ) uix = 1; else while( $1 < val[uix]+1 ) uix--
      num = $1 / (val[uix]+1)
      if( uix==1 ) n = "%5d   "; else n = "%8.2f"
      printf( "%s"n" %s%s\n", pfix, num, unit[uix], sfix ) 
   }'

Update  Here is a modified version of Gilles' script, as described in a comment to his answer ..(modified to suit my preferred look).

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}'
share|improve this question
1  
It looks like here we have a new standard tool in the making :) – Gowtham Jul 26 '12 at 18:57

4 Answers

up vote 3 down vote accepted

No, there is no such standard tool. Not even a GNU tool, though many GNU tools can produce this format and recent versions of GNU sort can sort numbers with units.

I find your code a bit convoluted. Here's a cleaner awk version (the output format isn't exactly identical):

awk '
    function human(x) {
        s="kMGTEPYZ";
        while (x>=1000 && length(s)>1)
            {x/=1024; s=substr(s,2)}
        return int(x+0.5) substr(s,1,1)
    }
    {gsub(/^[0-9]+/, human($1)); print}'

(Reposted from a more specialized question)

share|improve this answer
Okay, thanks. About your script, I basically really like it. There are a few things which caught my attention: (1) var s should be have leading B. Also this string is easily changed to IEC Binary notation. (2) It skips the 1000-1023 range in favour of 1<next size> (easily changed) (3) It does not have decimal values (which I do want). Again this is easily changed. When displaying 2 decimal places, the %f format causes a round-up to the <next size> for values 1019-1023; but it's not worth a workaround ..I've posted a modified version in my answer, for general reference. – Peter.O Jul 27 '12 at 8:17

As of Feb 2013 coreutils includes numfmt:

numfmt reads numbers in various representations and reformats them as requested. The most common usage is converting numbers to/from human representation (e.g. ‘4G’ ==> ‘4,000,000,000’).

E.g. :

echo 5607598768908 | numfmt --to=iec-i

outputs:

5.2Ti

Various other examples (including filtering, input/output processing etc) are presented HERE.

share|improve this answer

AFAIK there is no such standard tool to which you can pass text and it returns a human readable form. You may be able to find a package to accomplish the said task for your distro.

However, I do not understand why you may need such a tool. Most packages that give a related output, usually have a -h or equivalent switch for human-readable output.

share|improve this answer
1  
For purposes of understanding:  Human-readable means just that; readable by humans. The various different units of size shown by the tools you mention are not intended for programatic calculations, for which uniformity of units is essential. Working with bytes, which are always integers, is the only way bash can do any arithmetic with them. So... calculate in Bytes... report to in Human, eg. "You are about to permanently delete 3 files, totalling 2.44 GiB. Continue? – Peter.O Jul 26 '12 at 16:13
I think this should be part of your question. Looks to me like you've got the problem solved. Good luck. – shellter Jul 26 '12 at 22:20
1  
A common application is to generate numbers of bytes for sorting, and convert to human-readable units after sorting. – Gilles Jul 26 '12 at 23:44

There are a couple of perl modules on CPAN: Format::Human::Bytes and Number::Bytes::Human, the latter one being a bit more complete:

$ echo 100 1000 100000 100000000 |
  perl -M'Number::Bytes::Human format_bytes' -pe 's/\d{3,}/format_bytes($&)/ge'
100 1000 98K 96M

$ echo 100 1000 100000 100000000 |
  perl -M'Number::Bytes::Human format_bytes' -pe 's/\d{3,}/
   format_bytes($&,bs=>1000, round_style => 'round', precision => 2)/ge'
100 1.00k 100k 100M

And the reverse:

echo 100 1.00k 100K 100M 1Z |
  perl -M'Number::Bytes::Human parse_bytes' -pe '
    s/[\d.]+[kKMGTPEZY]/parse_bytes($&)/ge'
100 1024 102400 104857600 1.18059162071741e+21
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.