Generating a CUID (Collision-resistant Unique Identifier) in Bash is more complex compared to higher-level languages because Bash lacks built-in functions for some of the necessary operations, like generating random bytes or hashing. However, we can use external utilities like date
, openssl
, and hexdump
to achieve this.
Here is a step-by-step guide to generating a CUID in Bash:
Steps to Generate a CUID in Bash
- Timestamp: Use the current timestamp to ensure uniqueness over time.
- Counter: Implement a simple counter mechanism.
- Fingerprint: Use machine-specific values to avoid collisions.
- Randomness: Add random characters to further reduce the risk of collisions.
- Base36 Encoding: Encode the components using Base36 for readability.
Example Script
#!/bin/bash
# Base36 encoding function
encode_base36() {
local number=$1
local base36_chars="0123456789abcdefghijklmnopqrstuvwxyz"
local result=""
while [ "$number" -gt 0 ]; do
local remainder=$((number % 36))
result="${base36_chars:$remainder:1}$result"
number=$((number / 36))
done
echo "$result"
}
# Get current timestamp in milliseconds
timestamp=$(date +%s%3N)
# Simple counter mechanism
counter_file="/tmp/cuid_counter"
if [ ! -f "$counter_file" ]; then
echo 0 > "$counter_file"
fi
counter=$(cat "$counter_file")
counter=$((counter + 1))
echo "$counter" > "$counter_file"
# Machine-specific fingerprint (MD5 hash of hostname)
fingerprint=$(hostname | md5sum | cut -c1-4)
# Generate a random string of 4 characters
random=$(openssl rand -hex 2)
# Encode components in Base36
timestamp_base36=$(encode_base36 $timestamp)
counter_base36=$(encode_base36 $counter)
# Combine components to form the CUID
cuid="c${timestamp_base36}${counter_base36}${fingerprint}${random}"
echo "$cuid"
Explanation
Base36 Encoding:
- The
encode_base36
function converts a decimal number to a Base36 encoded string.
- The
Timestamp:
timestamp=$(date +%s%3N)
gets the current timestamp in milliseconds.
Counter:
- The counter value is stored in a temporary file
/tmp/cuid_counter
and is incremented each time a new CUID is generated.
- The counter value is stored in a temporary file
Machine Fingerprint:
- The
hostname | md5sum | cut -c1-4
command generates a machine-specific fingerprint by hashing the hostname and taking the first 4 characters.
- The
Random String:
openssl rand -hex 2
generates a 4-character random string.
Combine Components:
- The
c${timestamp_base36}${counter_base36}${fingerprint}${random}
line combines the components to form the final CUID.
- The
Summary
This script provides a basic implementation of generating a CUID in Bash. It uses external commands to handle timestamp generation, random number generation, and hashing, while a simple function handles Base36 encoding. This approach ensures that the generated CUIDs are unique, readable, and collision-resistant.