units: The Unit-Aware Calculator That's Been Sitting in /usr/bin Since v7

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:

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.

Key Takeaway: When your math has units attached, units(1) catches dimensional errors that bc and Python will silently compute wrong.

All newsletters