2026-07-09
Everyone reaches for bc or python -c when they need a quick calculation. Almost nobody reaches for units(1), which has been shipped with Unix since 1979 and knows the difference between a pound of force and a pound of mass, whether you can add furlongs to fathoms, and what a hogshead of ale is in liters. It's the calculator that refuses to let you make an error dimensional analysis would catch.
The core loop is dumb-simple: give it a "from" expression and a "to" unit, get an answer. But the database is enormous — /usr/share/units/definitions.units is roughly 7,000 entries on a stock GNU units — and the parser understands compound expressions with cancellation.
$ units "3 cups" "ml"
* 709.76471
/ 0.0014089098
$ units "60 mph" "furlongs/fortnight"
* 161280
/ 6.2003968e-06
$ units "planck length" meters
Definition: hbar c / (planck mass) = 1.6162550e-35 m
The killer feature is compound units with automatic cancellation. Try to convert nonsense and it refuses:
$ units "5 kg" "meters"
conformability error
5 kg
1 m
That's the whole point. bc will happily give you a number when you multiply grams by seconds; units will yell at you. This is dimensional analysis as a lint tool.
Terse mode makes it scriptable. The default two-line output is ergonomic at the prompt but awful in pipelines. -t gives you a bare number:
$ units -t "1 acre-foot" liters
1233481.9
$ ms=$(units -t "60 mph" "m/s") && echo "$ms"
26.8224
The temperature trap catches everyone once. Fahrenheit-to-Celsius has an offset, so a raw multiplication is wrong. units distinguishes a temperature reading from a temperature difference using function syntax:
$ units "tempF(72)" tempC # convert a reading
22.222222
$ units "72 degF" degC # convert a delta (72°F difference)
40
Both are valid; they mean different things. Every other calculator silently gets one of them wrong.
User-defined units live in ~/.units or whatever you pass with -f. This is where units becomes genuinely powerful for domain-specific work:
# ~/.units — my project's units file
rackU 1.75 inch
diskcost 0.018 dollars/gigabyte
awsgpuhour 3.06 dollars
trainingbudget 50000 dollars
$ units -f ~/.units "42 rackU" inches
* 73.5
$ units -f ~/.units "trainingbudget" awsgpuhour
* 16339.869
Now your BOM math, capacity planning, or cloud-cost estimates go through the same dimension-checking pipeline as everything else. Rename awsgpuhour to h100hour and every calculation that referenced it will still work — or fail loudly if you deleted it.
The obscure niceties:
units --verbose shows both the definition and the conversion — helpful when you're debugging why your "barrel" isn't the tool's "barrel" (there are seven).units -c checks the entire database for inconsistencies. Useful when writing a big custom file.units --search TERM greps the database for unit names. units --search planck is a fun rabbit hole.units_cur, and then 1 EUR becomes a first-class unit.If you deal with any physical quantity — networking (bits/bytes/packets/second), storage (IOPS × block size = MB/s), power (watt-hours vs. joules), even cloud billing — this is a 45-year-old tool that will save you from off-by-a-thousand embarrassments the first day you use it.
units(1) catches dimensional errors that bc and Python will silently compute wrong.
