A standard tool to convert a byte-count into human KiB MiB etc; like du, ls1
No, there is no such standard tool.
Since GNU coreutils 8.21 (Feb 2013, so not yet present in all distributions), on non-embedded Linux and Cygwin, you can use numfmt
. It doesn't produce exactly the same output format (as of coreutils 8.23, I don't think you can get 2 digits after the decimal points).
$ numfmt --to=iec-i --suffix=B --padding=7 1 177152 48832200 1975684956
1B
173KiB
47MiB
1.9GiB
Many older GNU tools can produce this format and GNU sort can sort numbers with units since coreutils 7.5 (Aug 2009, so present on modern non-embedded Linux distributions).
I find your code a bit convoluted. Here's a cleaner awk version (the output format isn't exactly identical):
awk '
function human(x) {
if (x<1000) {return x} else {x/=1024}
s="kMGTEPZY";
while (x>=1000 && length(s)>1)
{x/=1024; s=substr(s,2)}
return int(x+0.5) substr(s,1,1)
}
{sub(/^[0-9]+/, human($1)); print}'
(Reposted from a more specialized question)
As of v. 8.21
, 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.
printf %s\\n 5607598768908 | numfmt --to=iec-i
5.2Ti
Various other examples (including filtering, input/output processing etc) are presented HERE.
In addition, as of coreutils
v. 8.24
, numfmt
can process multiple fields with field range specifications similar to cut
, and supports setting the output precision with the --format
option
e.g.
numfmt --to=iec-i --field=2,4 --format='%.3f' <<<'tx: 180000 rx: 2000000'
tx: 175.782Ki rx: 1.908Mi
Here's a bash-only option, no bc
or any other non-builtins, + decimal format and binary units.
# Converts bytes value to human-readable string [$1: bytes value]
bytesToHumanReadable() {
local i=${1:-0} d="" s=0 S=("Bytes" "KiB" "MiB" "GiB" "TiB" "PiB" "EiB" "YiB" "ZiB")
while ((i > 1024 && s < ${#S[@]}-1)); do
printf -v d ".%02d" $((i % 1024 * 100 / 1024))
i=$((i / 1024))
s=$((s + 1))
done
echo "$i$d ${S[$s]}"
}
Examples:
$ bytesToHumanReadable 123456789
117.73 MiB
$ bytesToHumanReadable 1000000000000 # '1TB of storage'
931.32 GiB # 1TB of storage
$ bytesToHumanReadable
0 Bytes
$ bytesToHumanReadable 9223372036854775807
7.99 EiB
Should perform well on any version of Bash out there (including MSYSGit's Bash for Windows).