Skip to content
shellmap

Generate a UUID

Mint a random version-4 UUID (or, when ordering matters, a time-sortable UUIDv7) — for primary keys, idempotency tokens, request IDs, and any place a globally-unique identifier is needed without coordinating with a central allocator.

How to generate a uuid in each shell

Bashunix
uuidgen

Two flavors of `uuidgen` exist: the BSD/macOS `uuidgen` (lowercase output, present by default) and the Linux `uuid` package (separate binary, lowercase). Output: `f47ac10b-58cc-4372-a567-0e02b2c3d479`. For lowercase normalization: `uuidgen | tr "A-Z" "a-z"` (older macOS versions printed UPPERCASE; modern macOS 14+ prints lowercase). Zero-deps alternative on Linux: `cat /proc/sys/kernel/random/uuid` — kernel-generated, no install needed, slightly faster than forking `uuidgen`. For a UUID-like random string when nothing's available: `od -x -N16 /dev/urandom | head -1 | awk '{print $2$3"-"$4"-"$5"-"$6"-"$7$8$9}'` (NOT spec-compliant — missing version/variant bits — fine for opaque tokens, wrong for actual UUIDv4 consumers).

Zshunix
uuidgen

Same external. macOS ships `uuidgen` by default. Linux distros vary: Debian/Ubuntu ship `uuid-runtime` (`apt install uuid-runtime`) which provides `uuidgen`; Alpine ships `util-linux` (`apk add util-linux`). Or skip the install entirely with `cat /proc/sys/kernel/random/uuid`. For batch generation: `for i in {1..100}; do uuidgen; done` — but `uuidgen` reads `/dev/urandom` once per call; batch loops are CPU-bound on the fork overhead, not entropy.

Fishunix
uuidgen

Same external (no fish-native UUID builtin). For setting into a variable: `set request_id (uuidgen)`. Fish-friendly batch: `for i in (seq 100); uuidgen; end`. macOS-vs-Linux portability identical to bash; `command -q uuidgen; or echo 'install uuid-runtime'` is the conventional fish guard.

PowerShellwindows
[Guid]::NewGuid().ToString()

The .NET-native answer. `[Guid]::NewGuid()` returns a `Guid` object; `.ToString()` formats it (default `"D"` → `f47ac10b-58cc-4372-a567-0e02b2c3d479` with hyphens, no braces). Format variants: `.ToString("N")` no hyphens (`f47ac10b58cc4372a5670e02b2c3d479`); `.ToString("B")` braces (`{...}`); `.ToString("P")` parens (`(...)`). The .NET `Guid` is UUIDv4 by spec (version bits + RFC-compliant variant), generated from `RNGCryptoServiceProvider` — cryptographically secure. For UUIDv7 (time-sortable, monotonic per millisecond): pwsh has no built-in; install the `UUID` PowerShell module from PSGallery (`Install-Module UUID; New-UUID -Version 7`) or hand-roll from `[DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()` + random bytes per RFC 9562.

cmd.exewindows
powershell -NoProfile -Command "[Guid]::NewGuid().ToString()"

cmd has no native UUID. Shell out to pwsh (above), or to `uuidgen.exe` if installed (ships with Git for Windows in `C:\Program Files\Git\usr\bin\uuidgen.exe`). Capture: `for /f %i in ('powershell -NoP -C "[Guid]::NewGuid()"') do set UUID=%i`. WMI alternative (slow, deprecated): `wmic path Win32_ComputerSystem get UUID` — but that's the MACHINE's UUID, NOT a freshly-generated one. For a stable per-machine ID use that; for a per-request ID use the pwsh shell-out.

Equivalents listed for Bash, Zsh, Fish, PowerShell, cmd.exe.

Gotchas & notes

  • **UUIDv4 vs UUIDv7 (RFC 9562, 2024)**: UUIDv4 is 122 bits of randomness — unique with overwhelming probability, but UNORDERED, so consecutive inserts thrash B-tree indexes (every new row lands in a random leaf). UUIDv7 prepends a 48-bit Unix-millisecond timestamp, so generated IDs are MONOTONICALLY sortable — drop-in for autoincrement primary keys without the index thrashing. UUIDv7 is RFC 9562 (May 2024, replacing RFC 4122). Pwsh / .NET `Guid` is UUIDv4 only (as of .NET 9); UUIDv7 needs a module or hand-roll. PostgreSQL 18 ships `uuidv7()`; MySQL/MariaDB don't have it built in yet. Default to UUIDv7 for new database PKs unless you need UNGUESSABLE IDs (where v4 wins because the timestamp prefix of v7 leaks creation time).
  • **Where the version bits live**: in `xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx`, `M` is the version (4 for v4, 7 for v7, 1 for v1 time-based) and the first hex of `N` encodes the variant (8/9/a/b for RFC 4122 / 9562 variant). A "UUID" lacking these bits is a random-hex-string MASQUERADING as a UUID — many DBs and SDKs validate the version/variant nibbles and will reject malformed input. If you hand-roll: set bits explicitly. `od -x /dev/urandom | head -1` gives random bytes; ANDing/ORing the right nibbles to set version=4 + variant=10 produces a spec-compliant UUIDv4.
  • **Linux `uuidgen` vs `/proc/sys/kernel/random/uuid`**: both produce RFC 4122-compliant UUIDv4 from the same kernel CSPRNG. The `/proc` path is slightly faster (no fork, no library load) and works in minimal Alpine images that lack `util-linux`. macOS has no `/proc` filesystem — `uuidgen` is the only path there. For a fast portable bash function: `gen_uuid() { if [ -r /proc/sys/kernel/random/uuid ]; then cat /proc/sys/kernel/random/uuid; else uuidgen | tr A-Z a-z; fi; }`.
  • **UUID strings: case + format consistency**: UUIDs are case-INSENSITIVE per spec (`f47ac10b` and `F47AC10B` are equal). But database `=` comparison is BYTE-LEVEL — a row inserted with uppercase hex won't match a query with lowercase. Pick one convention site-wide (lowercase is the modern default — RFC 9562 recommends lowercase) and normalize at the application boundary. pwsh `[Guid]` always lowercases on `.ToString("D")`; macOS `uuidgen` lowercases since macOS 14; older `uuidgen` may produce uppercase — `tr A-Z a-z` is the safety net.

Related tasks