Last active 1 month ago

Generate rand password

rand_pass.sh Raw
1#!/bin/bash
2set -euo pipefail
3
4# ── Defaults ─────────────────────────────────────────────────────────
5DEFAULT_LENGTH=16
6CHARSET="alnum" # alnum | ascii
7
8# ── Usage ────────────────────────────────────────────────────────────
9usage() {
10 cat <<EOF
11Usage: $(basename "$0") [OPTIONS] [LENGTH]
12
13Generate a random password of the given length (default: ${DEFAULT_LENGTH}).
14
15Options:
16 -h, --help Show this help
17 -s, --special Include special characters (!@#\$%^&*_+-=)
18 -c, --copy Copy password to clipboard (requires wl-copy)
19
20Examples:
21 $(basename "$0") # 16-char alphanumeric password
22 $(basename "$0") 32 # 32-char alphanumeric password
23 $(basename "$0") -s 24 # 24-char password with special characters
24 $(basename "$0") -sc 20 # 20-char with specials, copied to clipboard
25EOF
26 exit 1
27}
28
29# ── Parse arguments ──────────────────────────────────────────────────
30FLAG_COPY=""
31
32while (( $# )); do
33 case "$1" in
34 -h|--help) usage ;;
35 -s|--special) CHARSET="ascii"; shift ;;
36 -c|--copy) FLAG_COPY=1; shift ;;
37 -sc|-cs) CHARSET="ascii"; FLAG_COPY=1; shift ;;
38 -*) echo "Unknown option: $1" >&2; usage ;;
39 *) break ;;
40 esac
41done
42
43LENGTH="${1:-$DEFAULT_LENGTH}"
44
45# ── Validate length ─────────────────────────────────────────────────
46if ! [[ "$LENGTH" =~ ^[0-9]+$ ]] || (( LENGTH <= 0 )); then
47 echo "Error: length must be a positive integer, got '${LENGTH}'" >&2
48 exit 1
49fi
50
51# ── Generate password ───────────────────────────────────────────────
52# tr character classes:
53# alnum -> [A-Za-z0-9]
54# ascii -> [A-Za-z0-9] + special characters
55generate_password() {
56 local len="$1"
57 local filter
58
59 case "$CHARSET" in
60 alnum) filter='A-Za-z0-9' ;;
61 ascii) filter='A-Za-z0-9!@#$%^&*_+\-=' ;;
62 esac
63
64 # Read enough random bytes to guarantee the desired length after filtering.
65 # tr may exit with SIGPIPE once head has enough bytes — that is expected.
66 LC_ALL=C tr -dc "$filter" </dev/urandom | head -c "$len" || true
67}
68
69PASSWORD="$(generate_password "$LENGTH")"
70
71# ── Output ───────────────────────────────────────────────────────────
72echo "$PASSWORD"
73
74# ── Copy to clipboard ───────────────────────────────────────────────
75if [[ -n "$FLAG_COPY" ]]; then
76 if command -v wl-copy &>/dev/null; then
77 echo -n "$PASSWORD" | wl-copy
78 echo "(copied to clipboard)" >&2
79 else
80 echo "Warning: wl-copy not found (install wl-clipboard)" >&2
81 fi
82fi