Last active
August 12, 2025 11:00
-
-
Save skull-squadron/aa37d6706503fd2fdc0dcd162f6719e5 to your computer and use it in GitHub Desktop.
Generate a random password of length N meeting complexity requirements in pure Bash 4+
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -Eeuo pipefail | |
| die() { | |
| echo >&2 "$@" | |
| echo >&2 | |
| echo >&2 "Usage: $(basename "$0") {{length>=1}} {{char_range[:min] ...}}" | |
| echo >&2 | |
| echo >&2 | |
| exit 1 | |
| } | |
| random_chars() { | |
| head /dev/random | LC_ALL=C tr -dc "$1" | head -c "$2" | |
| } | |
| length="${1-}" total_min=0 rest_charset='' r= | |
| if (($# < 2)) || [[ ! "$length" =~ ^[1-9][0-9]*$ ]]; then | |
| die 'Must specify length >= 1 and at least one character range' | |
| fi | |
| shift | |
| # Parse ranges and minimum requirements | |
| for arg in "$@"; do | |
| if [[ "$arg" =~ .+:[0-9]+$ ]]; then | |
| min=${arg##*:} charset=${arg%:*} | |
| if ((min == 0)); then | |
| rest_charset+="$charset" | |
| else | |
| r+="$(random_chars "$charset" "$min")" | |
| ((total_min += min)) | |
| fi | |
| else | |
| rest_charset+="$arg" | |
| fi | |
| done | |
| rest_length=$((length - total_min)) | |
| if ((rest_length < 0)); then | |
| die "Sum of minimum requirements ($total_min) exceeds password length ($length)" | |
| elif ((rest_length > 0)); then | |
| [[ "$rest_charset" ]] || die 'One or more character ranges must be specified without :N to generate remaining characters' | |
| r+=$(random_chars "$rest_charset" "$rest_length") | |
| fi | |
| # shuffle the result | |
| for ((i = ${#r}; i > 0; i--)); do | |
| j=$((SRANDOM % i)) | |
| echo -n "${r:$j:1}" | |
| r="${r:0:j}${r:j+1}" | |
| done | |
| echo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment