Bytes to human-readable size in Bash

numfmt --to=iec 123456789

numfmt --to=iec 123456789 prints 118M. It’s part of GNU coreutils, so most Linux systems have it. --to=iec divides by 1,024 and adds K, M, G; --to=si divides by 1,000:

numfmt --to=iec 123456789                # 118M
numfmt --to=iec-i --suffix=B 123456789   # 118MiB
numfmt --to=si 123456789                 # 124M
numfmt --to=si --format=%.1f 123456789   # 123.5M

Below 10 it keeps one decimal (4700000000 is 4.4G), and from 10 up it prints none. The tool below starts on the same 123456789 B: exactly 117.73756885528564453125 MiB and 123.456789 MB.

numfmt rounds up

124M for 123.46 million isn’t a typo. numfmt’s default is --round=from-zero, so any remainder rounds up, decimals included:

numfmt --to=iec --format=%.1f 123456789                  # 117.8M
numfmt --to=iec --round=nearest --format=%.1f 123456789  # 117.7M
numfmt --to=iec 1025                                     # 1.1K

Add --round=nearest when the number should match what JavaScript, Python or a spreadsheet print. Going back is lossy too: numfmt --from=iec 118M gives 123731968.

Pipes and columns

stat -c %s video.mp4 | numfmt --to=iec-i --suffix=B   # 118MiB
ls -l video.mp4 small.txt | numfmt --field=5 --to=iec
# -rw-r--r-- 1 root root       500 Oct 15 02:04 small.txt
# -rw-r--r-- 1 root root      118M Oct 15 02:04 video.mp4

Bash arithmetic can’t do this alone: it’s integer-only, so $(( 123456789 / 1048576 )) is 117.

ls, du and df

GNU ls -lh and du -h use 1,024 and the same letters, and they round up too. --si switches them to 1,000:

ls -lh video.mp4        # -rw-r--r-- 1 root root 118M Oct 15 02:04 video.mp4
ls -l --si video.mp4    # -rw-r--r-- 1 root root 124M Oct 15 02:04 video.mp4
du -h small.txt         # 4.0K	small.txt
du -h --apparent-size small.txt   # 500	small.txt

du counts the disk blocks a file takes, so a 500-byte file shows 4.0K; --apparent-size reports its length. For filesystems, df -h is binary and df -H decimal. A 1 GiB tmpfs:

df -h /data
# Filesystem      Size  Used Avail Use% Mounted on
# tmpfs           1.0G  118M  907M  12% /data
df -H /data
# Filesystem      Size  Used Avail Use% Mounted on
# tmpfs           1.1G  124M  951M  12% /data

macOS

macOS has no numfmt; brew install coreutils adds it as gnumfmt. The BSD tools differ from GNU’s: stat -f %z file replaces stat -c %s, ls -lh prints bytes with a B (500B), df -h writes 926Gi, ls has no --si, and du --si rounds to the nearest, so the same file is 123M there and 124M with GNU du. An awk line works on both systems:

echo 123456789 | awk '{ split("B KiB MiB GiB TiB PiB", u); i = 1; while ($1 >= 1023.95 && i < 6) { $1 /= 1024; i++ } printf "%.1f %s\n", $1, u[i] }'
# 117.7 MiB

The 1023.95 sends 1,048,575 bytes to 1.0 MiB rather than 1024.0 KiB.

Try it in the Data Size Converter

A number with a unit: 1.5 GB, 700 MiB, 8 Gb. Typed all lowercase, mb or kib reads as bytes; mixed, as in Mb, it reads as bits.

123456789 B is 123,456,789 bytes

UnitValueIn words
Bytes, decimal (SI) — each step ×1,000
B123,456,789bytes
kB123,456.789kilobytes
MB123.456789megabytes
GB0.123456789gigabytes
TB0.000123456789terabytes
PB0.000000123456789petabytes
Bytes, binary (IEC) — each step ×1,024
KiB120,563.2705078125kibibytes
MiB117.73756885528564453125mebibytes
GiB0.114978094585239887gibibytes
TiB0.000112283295493398327tebibytes
PiB0.000000109651655755271804pebibytes
Bits — 8 to a byte
bit987,654,312bits
Kb987,654.312kilobits
Mb987.654312megabits
Gb0.987654312gigabits
Tb0.000987654312terabits
Pb0.000000987654312petabits

SI units count by thousands and IEC units by 1,024s: 1 kB is 1,000 bytes, while 1 KiB is 1,024 — 2.4% more. This page reads KB as 1,000 bytes; some systems mean 1,024.

Runs in your browser. Nothing you enter is sent anywhere.