#!/bin/sh set -ue LC_ALL=C DEFAULT_PASSWORD_LENGTH=20 simple() { PASSWORD_LENGTH="${1:-$DEFAULT_PASSWORD_LENGTH}" tr -dc 'A-Za-z0-9@#%^&*()_+=-{}[]:;<>,.?/' < /dev/urandom | head -c "${PASSWORD_LENGTH}" | xargs echo } _shuf_line() { fold -w1 | shuf | tr -d '\n' } _gen_random_by_charset() { length="${1}" charset="${2}" tr -dc "${charset}" < /dev/random | head -c "${length}" } _gen_random_lower() { length="${1}" _gen_random_by_charset "${length}" '[:lower:]' } _gen_random_upper() { length="${1}" _gen_random_by_charset "${length}" '[:upper:]' } _gen_random_digits() { length="${1}" _gen_random_by_charset "${length}" '[:digit:]' } _gen_random_special() { length="${1}" _gen_random_by_charset "${length}" '!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~'\''' } protected() { readonly symbols_count_of_each_type=5 password="" password="${password}$(_gen_random_lower "${symbols_count_of_each_type}")" password="${password}$(_gen_random_upper "${symbols_count_of_each_type}")" password="${password}$(_gen_random_digits "${symbols_count_of_each_type}")" password="${password}$(_gen_random_special "${symbols_count_of_each_type}")" echo "${password}" | _shuf_line } if [ -z "${1+x}" ]; then simple "${DEFAULT_PASSWORD_LENGTH}" exit 0 fi main() { if [ "${1}" = "-p" ]; then protected exit 0 fi simple "${1}" exit 0 } main "${@}"