Skip to main content

Searching...

Tools
Articles
View All Results

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

Production Ready
bash
#!/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

bash
#!/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

bash
#!/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-0E02B2C3D479

Real-World Use Cases

1. Deployment script - unique release ID

bash
#!/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

bash
#!/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

bash
#!/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)

bash
# macOS - built-in, no install needed
bash
# Debian/Ubuntu
apt install uuid-runtime

# RHEL/CentOS
yum install util-linux

On 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.