Skip to content

Instantly share code, notes, and snippets.

@ernstki
Last active August 3, 2026 18:09
Show Gist options
  • Select an option

  • Save ernstki/8cde67c2593d10cd6e24f771f09fd5a9 to your computer and use it in GitHub Desktop.

Select an option

Save ernstki/8cde67c2593d10cd6e24f771f09fd5a9 to your computer and use it in GitHub Desktop.
Convert human-readable figures to/from byte sizes using AWK
#!/usr/bin/awk -f
##
## Author: Kevin Ernst <ernstki -at- mail.uc.edu
## Homepage: https://gist.github.com/ernstki/8cde67c2593d10cd6e24f771f09fd5a9
## License: Zero-Clause BSD (basically public domain)
##
## Notes: Library functions themselves should work with any AWK, but the
## self-tests in the `END` block will only run with Gawk, because
## they're using the three-argument `match` which is GNU-only
##
function humansize(b) {
if (b < 1024) return b
else if (b < 1024^2) return sprintf("%0.1fK", b/1024)
else if (b < 1024^3) return sprintf("%0.1fM", b/1024^2)
else if (b < 1024^4) return sprintf("%0.1fG", b/1024^3)
else if (b < 1024^5) return sprintf("%0.1fT", b/1024^4)
else return sprintf("%0.1fP", b/1024^5)
}
function dehumansize(s, u, n, i) {
gsub(/[[:space:]]/, "", s) # strip whitespace
if (index(s, "B") == 0) { # if no "B" at the end
u = substr(s, length(s))
n = substr(s, 1, length(s)-1)
} else {
u = substr(s, length(s)-1, 1)
n = substr(s, 1, length(s)-2)
}
i = index("kmgte", tolower(u))
#print s, u, n, i > "/dev/stderr"
return i ? sprintf("%0d", n * 1024^i) : s
}
END {
trials["humansize(1001)"] = "1001"
trials["humansize(1024)"] = "1.0K"
trials["humansize(1200)"] = "1.2K"
trials["humansize(2048)"] = "2.0K"
trials["humansize(10485760)"] = "10.0M"
trials["humansize(92274688)"] = "88.0M"
trials["humansize(13304090696090)"] = "12.1T"
trials["dehumansize(1001)"] = 1001
trials["dehumansize(1k)"] = 1024
trials["dehumansize(1K)"] = 1024
trials["dehumansize(1G)"] = 1073741824
trials["dehumansize(13.7G)"] = 14710262989
trials["dehumansize(88M)"] = 92274688
trials["dehumansize(12.1T)"] = 13304090696090
passed = failed = 0
eps = 1e-10 # accommodate very small deviations in FP precision
for (trial in trials) {
expected = trials[trial]
# Gawk only, because standard AWK is a pain here
if (match(trial, /^humansize\(([^)]+)\)/, arr))
actual = humansize(arr[1])
if (match(trial, /dehumansize\(([^)]+)\)/, arr))
actual = dehumansize(arr[1])
delta = (actual > expected) ? actual - expected : expected - actual
if (delta < eps * actual) {
printf " \033[32m✔\033[0m Passed: %s == %s\n", trial, expected
passed++
} else {
printf " \033[31m✘\033[0m Failed: Expected %s == %s, got %s\n", \
trial, expected, actual
failed++
}
}
printf "\nTotal: %d | \033[32mPassed: %d\033[0m | " \
"\033[31mFailed: %d\033[0m\n\n", passed + failed, passed, failed
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment