human

convert bytes to human readable formats
git clone git://git.2f30.org/human.git
Log | Files | Refs | README | LICENSE

commit b9a184f61f01aca16e52978b132f09edef80f40b
Author: z3bra <willy@mailoo.org>
Date:   Tue,  4 Nov 2014 00:17:47 +0100

first commit

Diffstat:
LICENSE | 14++++++++++++++
Makefile | 37+++++++++++++++++++++++++++++++++++++
README | 25+++++++++++++++++++++++++
human.1 | 42++++++++++++++++++++++++++++++++++++++++++
human.c | 125+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 243 insertions(+), 0 deletions(-)

diff --git a/LICENSE b/LICENSE @@ -0,0 +1,14 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. + diff --git a/Makefile b/Makefile @@ -0,0 +1,37 @@ +PREFIX:=/usr +MANPREFIX:=${PREFIX}/share/man + +CC = cc +LD= ${CC} +RM = rm +GZ = gzip +CFLAGS = -Wall -pedantic +LDFLAGS = + +.SUFFIXES: .c .o .gz +.PHONY : all clean install uninstall + +.c.o: + @echo -e "CC $<" + @${CC} -c ${CFLAGS} $< -o $@ + +human: human.o + @echo -e "LD human" + @${LD} $^ -o $@ ${LDFLAGS} + +human.1.gz: human.1 + @echo "GZ $<" + @${GZ} -c $< > $@ + +all : human human.1.gz + +clean : + ${RM} -f human *.o *.gz *~ + +install: human human.1.gz + install -D -m 0755 human ${DESTDIR}${PREFIX}/bin/human + install -D -m 0644 human.1.gz ${DESTDIR}${MANPREFIX}/man1/human.1.gz + +uninstall: + ${RM} ${DESTDIR}${PREFIX}/bin/human + ${RM} ${DESTDIR}${MANPREFIX}/man1/human.1.gz diff --git a/README b/README @@ -0,0 +1,25 @@ +╻ ╻╻ ╻┏┳┓┏━┓┏┓╻ +┣━┫┃ ┃┃┃┃┣━┫┃┗┫ +╹ ╹┗━┛╹ ╹╹ ╹╹ ╹ + -- by z3bra +======================== + +Human is a small program which translate numbers into a human readable format. +By default, it tries to detect the best factorisation, but you can force its +output. + +You can adjust the number of decimals by tweaking the environment variable +$SCALE. + + # convert 123456 to the best human factorisation + human 123456 + 120M + + # output 2 decimals + SCALE=2 human 123456 + 120.56K + + SCALE=3 human -m 123456 + 0.118M + +Well, that's it (and that's enough !) diff --git a/human.1 b/human.1 @@ -0,0 +1,42 @@ +.TH human 1 2014-09-03 "v3.0" "Human nanual" +.SH NAME +human \- output a number in human-readable format +.SH SYNOPSIS +.B human +.RI [ \-hkmgt ] <number> +.SH DESCRIPTION +.PP +.B human +takes the number given as an argument, and output it in a human readable format. +.TP +.B \-h +Displays a help text +.TP +.B \-k, -m, -g, -t +Force output in, respectively, KiB, MiB, GiB or TiB. +.SH ENVIRONMENT +.B SCALE +The special variable SCALE will allow you to choose how many numbers you want after the decimal point. +.SH EXAMPLES +.TP +\(buOutput a number in its best factorization form: +.EX +\fBhuman \fR12345 +\fR12K +.EE +.TP +\(buOutput a number with \fI3\fR numbers after the decimal point: +.EX +\fRSCALE=\-3 \fBhuman \fR12345 +\fR12.056K +.EE +.TP +\(buOutput a number in MiB, no matter what. +.EX +\fBhuman \fR-m 1234567890 +1177M +.EE +.SH REPORTING BUGS +If you encounter any bugs, feel free to report them at \fIwilly@mailoo.org\fR +.SH AUTHORS / CONTRIBUTORS +Willy Goiffon is the main author. diff --git a/human.c b/human.c @@ -0,0 +1,125 @@ +/* + * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + * Version 2, December 2004 + * + * Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> + * + * Everyone is permitted to copy and distribute verbatim or modified + * copies of this license document, and changing it is allowed as double + * as the name is changed. + * + * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + * + * 0. You just DO WHAT THE FUCK YOU WANT TO. + * + */ + +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <getopt.h> +#include <limits.h> + +#define TERA 1099511627776 +#define GIGA 1073741824 +#define MEGA 1048576 +#define KILO 1024 + +#define DEFAULT_SCALE 0 + +/* + * calculate a power of number + * disclaimers: return no more than a "long" so use wisely... + * + */ +long power (long number, int pow) +{ + return pow > 0 ? power(number * number, pow - 1) : number; +} + +/* + * read the environment varaible "SCALE" and returns its value. + * returns DEFAULT_SCALE if it does not return a number. + * + */ +int getscale() +{ + /* would you rather use getenv() twice ? or allocate a pointer ? */ + char *scale = NULL; + scale = getenv("SCALE"); + + /* in atoi, we trust. maybe. */ + return scale ? atoi(scale) : DEFAULT_SCALE; +} + +/* + * calculate the best factorization for a number, depending on its value. + * actual max factorisation is 1024^3 (TiB) + * + */ +char factorize (double number) +{ + return number >= TERA ? 'T' : + number >= GIGA ? 'G' : + number >= MEGA ? 'M' : + number >= KILO ? 'K' : + 0; +} + +/* + * calculate a human-readable version of the given number, depending of the + * factorisation level given. + * + */ +double humanize (double number, char factor) +{ + int pow = 0; + + /* cascading switch. note a lack of "break" statements */ + switch (factor) { + case 'T' : pow++; + case 'G' : pow++; + case 'M' : pow++; + case 'K' : break; + default : return number; + } + + /* return the number divided by the correct factorization level */ + return number /= power(1024, pow); +} + +int main (int argc, char **argv) +{ + char ch, fac = 0; + double number = 0; + + /* only switches are use to force factorization */ + while ((ch = getopt(argc, argv, "hkmgt")) != -1) { + switch (ch) { + case 'h': + printf("usage: %s [-hkmgt] <number>\n", argv[0]); + exit(0); + break; + case 't': fac ='T'; break; + case 'g': fac ='G'; break; + case 'm': fac ='M'; break; + case 'k': fac ='K'; break; + } + } + + /* get the number. if there is not, strtold will return 0 */ + number = strtold(argv[argc - 1], NULL); + + if (number < 0) { + errx(EXIT_FAILURE, "I ain't gonna do it. Deal with it."); + } + + /* use explicit factorization. otherwise, guess the best one */ + fac = fac > 0 ? fac : factorize(number); + + /* actually print the result, isn't that what we're here for after all ? */ + printf("%.*f%c\n", getscale(), humanize(number, fac), fac); + + return 0; +}