zsh-users
 help / color / mirror / code / Atom feed
* Converting bash script to zsh for converting bytes to 'readable'
@ 2018-09-12 22:02 TJ Luoma
  2018-09-12 22:38 ` TJ Luoma
  2018-09-12 23:04 ` Daniel Shahaf
  0 siblings, 2 replies; 5+ messages in thread
From: TJ Luoma @ 2018-09-12 22:02 UTC (permalink / raw)
  To: Zsh-Users List

[-- Attachment #1: Type: text/plain, Size: 1833 bytes --]

Several years ago I came across this script (below) as a 'bash' script. I
believe the comments came from the original as well:


BYTES="$@"

#MBYTES='1024'
MBYTES='1000'

# Array of suffixes
declare -a METRIC=(' Bytes' 'KB' 'MB' 'GB' 'TB' 'XB' 'PB')

# magnitude of 2^10
MAGNITUDE=0

# change this numeric value to increase decimal precision
PRECISION="scale=1"

# numeric arg val (in bytes) to be converted
UNITS=$(echo "$BYTES" | tr -dc '[0-9]')

# compares integers (b/c no floats in bash)
while [ ${UNITS/.*} -ge ${MBYTES} ]
do
# floating point math via `bc`
UNITS=`echo "$PRECISION; $UNITS/${MBYTES}" | bc`

# increments counter for array pointer
((MAGNITUDE++))
done

echo "$BYTES bytes"

echo "$UNITS ${METRIC[$MAGNITUDE]}"

I don't really understand what the 'while' loop is doing, and I don't know
if zsh has 'floats' (which I assume is 'floating point'?).

So, given my limited knowledge here, I tried to implement the same thing in
zsh, and this is what I came up with:

BYTES="$@"

#MBYTES='1024'
MBYTES='1000'

PRECISION="scale=2"

if [ "$MBYTES" = "1000" ]
then
METRIC=('KB' 'MB' 'GB' 'TB' 'XB' 'PB')
else
METRIC=('KiB' 'MiB' 'GiB' 'TiB' 'XiB' 'PiB')
fi

for BYTES in "$@"
do

MAGNITUDE=0

UNITS=$(echo "$BYTES" | tr -dc '[0-9]')

if [[ "$UNITS" != "" ]]
then

while [ ${UNITS/.*} -ge $MBYTES ]
do
UNITS=$(echo "$PRECISION; $UNITS/$MBYTES" | bc)

((MAGNITUDE++))

done

echo "$UNITS ${METRIC[$MAGNITUDE]}"

fi

done


Does that look correct to you? Did I miss anything? It appears to work in
my (limited, so far) testing, but I'm worried that I'm overlooking
something.

Alternatively: is there another / easier way of doing this that I should
use instead? Some 'zmodload' or something?

Thanks for any pointers.

Tj



--
TJ Luoma
TJ @ MacStories
Personal Website: luo.ma (aka RhymesWithDiploma.com)
Twitter: @tjluoma

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Converting bash script to zsh for converting bytes to 'readable'
  2018-09-12 22:02 Converting bash script to zsh for converting bytes to 'readable' TJ Luoma
@ 2018-09-12 22:38 ` TJ Luoma
  2018-09-12 22:52   ` Bart Schaefer
  2018-09-12 23:04 ` Daniel Shahaf
  1 sibling, 1 reply; 5+ messages in thread
From: TJ Luoma @ 2018-09-12 22:38 UTC (permalink / raw)
  To: Zsh-Users List

[-- Attachment #1: Type: text/plain, Size: 280 bytes --]

Hrm… I had definitely indented the code in my original message, but
somewhere along the line, it all got "outdented".

I hope it's clear enough based on context.

Tj

--
TJ Luoma
TJ @ MacStories
Personal Website: luo.ma (aka RhymesWithDiploma.com)
Twitter: @tjluoma

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Converting bash script to zsh for converting bytes to 'readable'
  2018-09-12 22:38 ` TJ Luoma
@ 2018-09-12 22:52   ` Bart Schaefer
  0 siblings, 0 replies; 5+ messages in thread
From: Bart Schaefer @ 2018-09-12 22:52 UTC (permalink / raw)
  To: TJ Luoma; +Cc: Zsh Users

[-- Attachment #1: Type: text/plain, Size: 359 bytes --]

On Wed, Sep 12, 2018, 3:39 PM TJ Luoma <luomat@gmail.com> wrote:

> Hrm… I had definitely indented the code in my original message, but
> somewhere along the line, it all got "outdented".
>

The Gmail editor will do that unless you select Plain Text from the More
Options menu in the lower right corner.

Even then it will wrap long lines.


>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Converting bash script to zsh for converting bytes to 'readable'
  2018-09-12 22:02 Converting bash script to zsh for converting bytes to 'readable' TJ Luoma
  2018-09-12 22:38 ` TJ Luoma
@ 2018-09-12 23:04 ` Daniel Shahaf
  2018-09-12 23:08   ` Daniel Shahaf
  1 sibling, 1 reply; 5+ messages in thread
From: Daniel Shahaf @ 2018-09-12 23:04 UTC (permalink / raw)
  To: TJ Luoma; +Cc: Zsh-Users List

TJ Luoma wrote on Wed, Sep 12, 2018 at 18:02:26 -0400:
> I don't really understand what the 'while' loop is doing, and I don't know
> if zsh has 'floats' (which I assume is 'floating point'?).
> 

Yes, zsh has floating point variables, for example, 'typeset -F foo'.

The 'while' loop divides the number by 1000 in each iteration to figure
out the magnitude.  It's like counting digits to figure out the exponent
to use for scientific notation (1024 == 1.024e+3).

> METRIC=('KB' 'MB' 'GB' 'TB' 'XB' 'PB')

This should read KB MB GB TB PB EB ZB YB.

> Does that look correct to you? Did I miss anything? It appears to work in
> my (limited, so far) testing, but I'm worried that I'm overlooking
> something.
> 

It may be correct, but it's not idiomatic.  For one, it's not idiomatic
to treat floating point numbers as strings.  I'm not sure what scale=2
to bc(1) does but it's probably possible to do that in native zsh too.
Likewise for the tr(1) though that's not as crucial.

For instance, the loop could have been written like this:
.
    while (( UNITS <= MBYTES )); do
.
(but read on)

> Alternatively: is there another / easier way of doing this that I should
> use instead? Some 'zmodload' or something?

I think this does what you want?

     1	zmodload zsh/mathfunc
     2	f() {
     3	  setopt localoptions ksharrays
     4	  integer i=$(( log2( $1 )/10 )) 
     5	  local -a SI=( '' 'Ki' 'Mi' 'Gi' )
     6	  printf '%5.2g %s\n' "$(( ($1)*1.0 / (1<<(10*i)) ))" "${SI[i]}B"
     7	}

Explanation (by line number)

1: Enables the 'log2' math function (requires zsh 5.6)

3: I'd like to use zero-based array indexes, purely for convenience.
(I could've changed [i] to [i+1] on line 7 instead.)

4: Take the base-2 logarithm of the input and divide it by 10 to get the
order of magnitude.  Using an integer variable implicitly truncates the
input.  (You may prefer rounding to truncating, in order for 1023 to map
to KiB rather than to plain B.)

6: Divide the input by the largest power of 1024 smaller than it, printf
that, and append the appropriate SI prefix from the lookup array.
Multiply by 1.0 to ensure at least one of the arguments to '/' is a
float, in order for the division expression to evaluate to a floating
point quantity.  (Integer division results in an integer: compare
$((5/2)) and $((5.0/2)).)

Cheers,

Daniel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Converting bash script to zsh for converting bytes to 'readable'
  2018-09-12 23:04 ` Daniel Shahaf
@ 2018-09-12 23:08   ` Daniel Shahaf
  0 siblings, 0 replies; 5+ messages in thread
From: Daniel Shahaf @ 2018-09-12 23:08 UTC (permalink / raw)
  To: TJ Luoma; +Cc: Zsh-Users List

Daniel Shahaf wrote on Wed, Sep 12, 2018 at 23:04:45 +0000:
>      1	zmodload zsh/mathfunc
>      2	f() {
>      3	  setopt localoptions ksharrays
>      4	  integer i=$(( log2( $1 )/10 )) 
>      5	  local -a SI=( '' 'Ki' 'Mi' 'Gi' )
>      6	  printf '%5.2g %s\n' "$(( ($1)*1.0 / (1<<(10*i)) ))" "${SI[i]}B"
>      7	}

A subtle point here: in an arithmetic expression, using raw variable names
behave as one'd expect, but using variable expansions does not.  Compare:

% s='1+1'
% echo $(( s * 2 )) 
4
% echo $(( $s * 2 ))
3
% 

That's why I put parentheses around the «$1» in the math expression: that
ensures consistent parsing even if $1 is an expression (as in «f "1024+1024"»).

Cheers,

Daniel
(It's exactly the same issue as with C macros)

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-09-12 23:09 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-12 22:02 Converting bash script to zsh for converting bytes to 'readable' TJ Luoma
2018-09-12 22:38 ` TJ Luoma
2018-09-12 22:52   ` Bart Schaefer
2018-09-12 23:04 ` Daniel Shahaf
2018-09-12 23:08   ` Daniel Shahaf

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).