-
-
Save tsujp/b306fdb5e832c3fbd775ef523a88a93a to your computer and use it in GitHub Desktop.
Generate random strings or dictionary words in Bash
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 | |
# get a random-character password | |
# First argument is password length | |
# Can override the default character set by passing in PWCHARSET=<charset> as env | |
randompass() { | |
# globbing & history expansion here is a pain, so we store its state, temp turn it off & restore it later | |
local maybeglob="$(shopt -po noglob histexpand)" | |
set -o noglob # turn off globbing | |
set +o histexpand # turn off history expansion | |
if [ $# -eq 0 ]; then | |
echo "Usage: randompass <length>" | |
return 1 | |
fi | |
# allow overriding the password character set with env var PWCHARSET | |
# NOTE that we DELETE THE CAPITAL O, CAPITAL I AND LOWERCASE L CHARACTERS | |
# DUE TO SIMILARITY TO 1 AND 0 | |
# (but only if you use the default alnum set) | |
# BECAUSE WHO THE FUCK EVER THOUGHT THAT WOULD BE A GOOD IDEA? 😂 | |
if [ -z "$PWCHARSET" ]; then | |
local lower=$(echo -n {a..z} | tr -d ' ') | |
local upper=$(echo -n {A..Z} | tr -d ' ') | |
local num=$(echo -n {0..9} | tr -d ' ') | |
local alcharacterset="$lower$upper" | |
local alnumcharacterset=$(printf "%s" "$alcharacterset$num" | tr -d 'OlI') | |
local punc='!@#$%^&*-_=+[]{}|;:,.<>/?~' | |
local PWCHARSET="$alnumcharacterset$punc" | |
fi | |
# ...but also intersperse it with spaces so that the -e option to shuf works. | |
# Using awk to split the character set into a space-separated string of characters. | |
# Saw some noise that empty field separator will cause awk problems, | |
# but it's concise and fast and works, so... &shrug; | |
# printf is necessary due to some of the punctuation characters being interpreted when using echo | |
local characterset=$(printf "%s" "$PWCHARSET" | awk NF=NF FS="") | |
{ shuf --random-source=/dev/urandom -n $1 -er $characterset; } | tr -d '\n' | |
echo | |
# restore any globbing state | |
eval "$maybeglob" | |
# cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9\!\@\#\$\%\&\*\?' | fold -w $1 | head -n 1 | |
} | |
# get a random-dictionary-word password | |
# First argument is minimum word length | |
# Second argument is number of words to generate | |
randompassdict() { | |
if [ $# -eq 0 ]; then | |
echo "Usage: randompassdict <num-words> [<min-word-length> [<max-word-length>]]" | |
return 1 | |
fi | |
local numwords=$1 | |
local minlen=${2:-8} | |
local maxlen=${3:-99} | |
# take the dict, filter out anything not within the min/max length or that has apostrophes, and shuffle | |
local pool=$(cat /usr/share/dict/words | awk 'length($0) >= '$minlen' && length($0) <= '$maxlen' && $0 ~ /^[^'\'']+$/') | |
local poolsize=$(printf "%s" "$pool" | wc -l) | |
# why is poolsize getting spaces in front? No idea. Removing them. | |
poolsize=${poolsize##* } | |
local words=$(echo -n "$pool" | shuf -n "$numwords" | tr '\n' ' ') | |
echo "$words" | |
echo "(out of a possible $poolsize available words in the dictionary that suit the requested length range [$minlen-$maxlen])" 1>&2 | |
# a former attempt that worked but was less flexible: | |
#cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9\!\@\#\$\%\&\*\?' | fold -w $1 | head -n $2 | tr '\n' ' ' | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment