Generating UUIDs in Bash: Multiple Methods with Code Examples


2 views

Universally Unique Identifiers (UUIDs) are essential for generating distinct identifiers in distributed systems. While many languages provide built-in UUID generation, Bash requires external tools or creative solutions.

The simplest approach on Unix-like systems:

# Generate version 4 random UUID
uuid=$(uuidgen)
echo "Generated UUID: $uuid"

# Generate version 1 time-based UUID
uuid=$(uuidgen -t)
echo "Time-based UUID: $uuid"

On modern Linux systems:

uuid=$(cat /proc/sys/kernel/random/uuid)
echo "Kernel-generated UUID: $uuid"

When other tools aren't available:

uuid=$(openssl rand -hex 16 | awk '{print substr($0,1,8)"-"substr($0,9,4)"-"substr($0,13,4)"-"substr($0,17,4)"-"substr($0,21,12)}')
echo "OpenSSL-generated UUID: $uuid"

For environments with no external tools:

generate_uuid() {
    local N B C='89ab'
    for (( N=0; N < 16; ++N ))
    do
        B=$(( RANDOM%256 ))
        case $N in
            6) printf '4%x' $(( B%16 )) ;;
            8) printf '%c%x' ${C:$(( RANDOM%${#C} )):1} $(( B%16 )) ;;
            3 | 5 | 7 | 9) printf '%02x-' $B ;;
            *) printf '%02x' $B ;;
        esac
    done
    echo
}

uuid=$(generate_uuid)
echo "Pure Bash UUID: $uuid"

To verify your UUIDs conform to RFC 4122:

validate_uuid() {
    local uuid_pattern='^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'
    if [[ $1 =~ $uuid_pattern ]]; then
        echo "Valid UUID: $1"
    else
        echo "Invalid UUID format" >&2
        return 1
    fi
}

Benchmarking different methods (on Ubuntu 20.04):

# uuidgen
time for i in {1..1000}; do uuidgen >/dev/null; done
# real 0m0.798s

# /proc method
time for i in {1..1000}; do cat /proc/sys/kernel/random/uuid >/dev/null; done
# real 0m0.112s

# OpenSSL
time for i in {1..1000}; do openssl rand -hex 16 >/dev/null; done
# real 0m1.342s

# Pure Bash
time for i in {1..1000}; do generate_uuid >/dev/null; done
# real 0m3.876s

Practical applications for UUIDs in Bash:

# Temporary file with UUID
temp_file="/tmp/$(uuidgen).log"
echo "Data" > "$temp_file"

# Database record identification
db_insert() {
    local id=$(uuidgen)
    sqlite3 db.sqlite "INSERT INTO records VALUES('$id', '$1')"
}

# Distributed locking
lock_file="/var/lock/$(uuidgen)"
if mkdir "$lock_file"; then
    # Critical section
    rm -rf "$lock_file"
else
    echo "Process already running"
fi

UUIDs (Universally Unique Identifiers) are 128-bit numbers used to uniquely identify information in computer systems. While Java provides UUID.randomUUID(), Bash requires different approaches.

The simplest way to generate a UUID in Bash is using the uuidgen utility, typically pre-installed on most Linux distributions:

# Generate a random UUID
uuid=$(uuidgen)
echo $uuid

For systems without uuidgen, you can read from the kernel's random UUID generator:

# Read UUID from kernel
uuid=$(cat /proc/sys/kernel/random/uuid)
echo $uuid

If you have Python installed, this provides a cross-platform solution:

# Generate UUID with Python
uuid=$(python -c 'import uuid; print(uuid.uuid4())')
echo $uuid

For environments with limited tools, here's a Bash function that generates UUIDv4:

generate_uuid() {
    local N B C='89ab'
    for (( N=0; N < 16; ++N )); do
        B=$(( $RANDOM%256 ))
        case $N in
            6) printf '4%x' $(( B%16 )) ;;
            8) printf '%c%x' ${C:$RANDOM%${#C}:1} $(( B%16 )) ;;
            3 | 5 | 7 | 9) printf '%02x-' $B ;;
            *) printf '%02x' $B ;;
        esac
    done
    echo
}

To verify your UUIDs are properly formatted:

# Check UUID format
if [[ $uuid =~ ^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ ]]; then
    echo "Valid UUIDv4"
else
    echo "Invalid UUID"
fi

When generating many UUIDs in scripts:

  • uuidgen is fastest (100k in ~2.5s)
  • Kernel method is slightly slower (100k in ~3s)
  • Python adds overhead (100k in ~12s)
  • Pure Bash is slowest (100k in ~45s)

Common applications include:

# Temporary file with UUID
temp_file="/tmp/$(uuidgen).tmp"
touch "$temp_file"

# Unique directory creation
mkdir "data-$(uuidgen | cut -c1-8)"