Developer Lab · Bash
Generate UUID in Bash
uuidgen is built into Linux and macOS - zero dependencies, reads directly from the kernel entropy pool. Also available via /proc/sys/kernel/random/uuid on Linux.
Quick Reference
| Method | Platform | Version | Notes |
|---|---|---|---|
| uuidgen | Linux + macOS | v4 random (Linux + macOS) | Most portable - lowercase on Linux, uppercase on macOS |
| /proc/sys/kernel/random/uuid | Linux only | v4 | Kernel-generated, always random |
| python3 -c "import uuid..." | Any | v4 | Fallback when uuidgen unavailable |
Primary Implementation
#!/usr/bin/env bash
# ── Method 1: uuidgen (Linux + macOS) ──────────────────────────
# Both Linux and macOS generate a random v4 UUID by default
# (Linux outputs lowercase, macOS outputs uppercase)
uuidgen # v4 random
uuidgen | tr '[:upper:]' '[:lower:]' # normalize to lowercase
# ── Method 2: /proc virtual file (Linux only) ──────────────────
# The kernel generates a fresh v4 UUID on every read
cat /proc/sys/kernel/random/uuid
# ── Method 3: Python fallback (any platform) ──────────────────
python3 -c "import uuid; print(uuid.uuid4())"
# ── Assign to a variable ──────────────────────────────────────
UUID=$(uuidgen | tr '[:upper:]' '[:lower:]')
echo "Generated: $UUID"
# ── Generate multiple UUIDs ───────────────────────────────────
for i in {1..5}; do
uuidgen | tr '[:upper:]' '[:lower:]'
done
# ── Validate a UUID with regex ────────────────────────────────
validate_uuid() {
local uuid="$1"
if [[ "$uuid" =~ ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ ]]; then
echo "Valid UUID"
else
echo "Invalid UUID"
fi
}
validate_uuid "$(uuidgen | tr '[:upper:]' '[:lower:]')"All Approaches
Cross-platform portable function
#!/usr/bin/env bash
# Portable UUID v4 generator - works on Linux and macOS
generate_uuid() {
if command -v uuidgen &>/dev/null; then
# uuidgen outputs random v4 on both; normalize to lowercase
uuidgen | tr '[:upper:]' '[:lower:]'
elif [[ -r /proc/sys/kernel/random/uuid ]]; then
cat /proc/sys/kernel/random/uuid
elif command -v python3 &>/dev/null; then
python3 -c "import uuid; print(uuid.uuid4())"
else
echo "Error: no UUID generator found" >&2
return 1
fi
}
UUID=$(generate_uuid)
echo "$UUID"No hyphens / uppercase variants
#!/usr/bin/env bash
# Lowercase with hyphens (standard)
UUID_LOWER=$(uuidgen | tr '[:upper:]' '[:lower:]')
echo "$UUID_LOWER"
# → f47ac10b-58cc-4372-a567-0e02b2c3d479
# No hyphens (32 hex chars)
UUID_HEX=$(uuidgen | tr -d '-' | tr '[:upper:]' '[:lower:]')
echo "$UUID_HEX"
# → f47ac10b58cc4372a5670e02b2c3d479
# Uppercase (default on macOS)
UUID_UPPER=$(uuidgen)
echo "$UUID_UPPER"
# → F47AC10B-58CC-4372-A567-0E02B2C3D479Real-World Use Cases
1. Deployment script - unique release ID
#!/usr/bin/env bash
set -euo pipefail
RELEASE_ID=$(uuidgen | tr '[:upper:]' '[:lower:]')
DEPLOY_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
echo "Starting deployment: $RELEASE_ID at $DEPLOY_TIME"
# Tag the Docker image with the release UUID
docker build -t "myapp:$RELEASE_ID" .
docker push "myapp:$RELEASE_ID"
# Write release metadata
cat > release.json <<EOF
{
"releaseId": "$RELEASE_ID",
"deployedAt": "$DEPLOY_TIME",
"image": "myapp:$RELEASE_ID"
}
EOF
echo "Deployment $RELEASE_ID complete"2. Log file with unique session ID
#!/usr/bin/env bash
SESSION_ID=$(uuidgen | tr '[:upper:]' '[:lower:]')
LOG_FILE="/var/log/myapp/session-${SESSION_ID}.log"
log() {
echo "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] [$SESSION_ID] $*" | tee -a "$LOG_FILE"
}
log "Session started"
log "Running backup..."
# ... backup logic ...
log "Backup complete"3. Temp directory with UUID name
#!/usr/bin/env bash
# Create a unique temp directory - no collision risk
WORK_DIR="/tmp/job-$(uuidgen | tr '[:upper:]' '[:lower:]')"
mkdir -p "$WORK_DIR"
# Ensure cleanup on exit
trap "rm -rf '$WORK_DIR'" EXIT
echo "Working in: $WORK_DIR"
# ... do work in $WORK_DIR ...
echo "Done - temp dir will be cleaned up"Common Mistakes
Assuming uuidgen output case is the same everywhere
On Linux, uuidgen outputs lowercase v4 UUIDs; on macOS it outputs uppercase. Both are random v4 - normalize with tr '[:upper:]' '[:lower:]' when case matters. For a time-based v1 on Linux, use uuidgen -t.
Using $RANDOM for unique IDs
$RANDOM only provides 15 bits of entropy (0 - 32767). It is not CSPRNG-backed and has a very high collision probability. Never use it for unique identifiers.
Not quoting UUID variables in shell scripts
Always quote UUID variables: "$UUID" not $UUID. While UUIDs don't contain spaces, it's a good habit and prevents issues if the variable is ever empty.
How It Works
uuidgen on Linux reads from /dev/urandom (the kernel CSPRNG) to generate 16 random bytes, then formats them as a UUID v4 string.
/proc/sys/kernel/random/uuid is a virtual file - the Linux kernel generates a fresh v4 UUID on every read() call. It's slightly faster than spawning uuidgen as a subprocess.
On macOS, uuidgen is part of the system and produces a random v4 UUID (uppercase) using the OS CSPRNG.
Output Formats
uuidgen (macOS, uppercase)
F47AC10B-58CC-4372-A567-0E02B2C3D479
lowercase
f47ac10b-58cc-4372-a567-0e02b2c3d479
no hyphens
f47ac10b58cc4372a5670e02b2c3d479
Best Practices, Performance, and Security
Best practices
uuidgen already outputs a random v4 UUID on Linux and macOS - no extra flags needed.
Pipe through tr '[:upper:]' '[:lower:]' for consistent lowercase output.
Write a portable generate_uuid() function that falls back gracefully across platforms.
Performance
Each uuidgen call spawns a subprocess - fast for occasional use but not suitable for generating thousands of UUIDs in a loop. For bulk generation in scripts, use Python or a compiled tool.
Reading /proc/sys/kernel/random/uuid avoids subprocess overhead on Linux - it's a direct kernel call.
Security
Entropy source: /dev/urandom on Linux (kernel CSPRNG), SecRandomCopyBytes on macOS. Cryptographically secure.
Suitable for deployment IDs, session tokens in scripts, and unique file/directory names. Never use $RANDOM or date +%s for security-sensitive IDs.
Installation
UUID v4 (uuidgen)
# macOS - built-in, no install needed# Debian/Ubuntu
apt install uuid-runtime
# RHEL/CentOS
yum install util-linuxOn most modern Linux distros, uuidgen is pre-installed as part of util-linux.
Frequently Asked Questions
How do I generate a UUID in Bash?
uuidgen is built into Linux and macOS with zero dependencies and reads directly from the kernel entropy pool. Run uuidgen for a random v4 UUID, or uuidgen -t for a time-based v1. On Linux you can also read /proc/sys/kernel/random/uuid.
Is uuidgen cryptographically secure?
Yes. uuidgen uses the platform CSPRNG (operating system secure random source), suitable for session tokens, API keys, and idempotency keys. Do not use non-cryptographic random sources for security-sensitive identifiers.
What is the difference between UUID v4 and v7 in Bash?
UUID v4 (uuidgen or equivalent) is fully random and not sortable. UUID v7 embeds a millisecond timestamp for chronological sorting (RFC 9562). Use v4 for general-purpose IDs; use v7 for database primary keys at scale.
Do I need to install a package for UUID generation in Bash?
No additional package is required for basic v4 generation in Bash. Check the Installation section for version-specific notes.
How do I validate a UUID string in Bash?
Use the platform's UUID parse/validation function, or test against the RFC 4122 regex: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i. Always validate external input at API boundaries.
Should I use UUIDs as database primary keys in Bash applications?
UUIDs work well as primary keys for distributed systems. Prefer native UUID/BINARY(16) column types over VARCHAR(36). For very large tables, consider UUID v7 for better B-tree insert locality.
Can I generate UUIDs in Bash without a network connection?
Yes. UUID generation uses local OS entropy sources and does not require network access. Each call is independent and thread-safe on modern platforms.
What output formats are available in Bash?
The standard hyphenated lowercase string (36 chars) is the default. Most APIs also support 32-char hex (no hyphens) and 16-byte binary formats. Use string format for APIs and binary for database storage.
What RFC standards apply to Bash UUID generation?
Version 4 UUIDs follow RFC 4122. UUID v7 follows RFC 9562 (May 2024). Ensure your chosen method produces compliant version and variant bits.
When should I avoid UUID v1?
Avoid UUID v1 in security-sensitive contexts - it embeds MAC address and timestamp information. Prefer v4 (uuidgen or equivalent) unless you need legacy Cassandra timeuuid compatibility.
Key definitions
- UUID
- 128-bit universally unique identifier, usually shown as 36 hex characters with hyphens.
- CSPRNG
- Cryptographically secure pseudo-random number generator - the entropy source behind secure UUID generation.
- RFC 4122
- IETF standard defining UUID versions 1 through 5. Version 4 is random.
- RFC 9562
- IETF standard adding UUID versions 6, 7, and 8. Version 7 is time-ordered.