correcthorse, in 27 lines of bash

http://xkcd.com/936/

Not worth creating a project for, and it might be interesting to see what changes people would make.

Non-standard dependencies:

  • words, for the dictionary
  • zsh (this will probably work just fine with bash, though, too)
#!/usr/bin/zsh
# Author: @sxan@midwest.social
# 2025-02-23

final=(xargs echo)
count=6
while getopts d opt; do
	case $opt in
		d)
			final=(tr 'A-Z' 'a-z')
			;;
		*)
			printf "Password generator based on the correcthorse algorithm from http://xkcd.com/936//n/n"
			printf "USAGE: %s [-d] [#]\n" "$0"
			printf " -d  make the result all lower case; otherwise, each word will be capitalized.\n"
			printf " #   the number of words to include. Defaults to 6."
			exit 1
			;;
	esac
done
shift $(($OPTIND - 1))
[[ $# -gt 0 ]] && count=$*

shuf -n $((count * 2)) /usr/share/dict/american-english | \
	sed 's/'"'"'.*//; s/^\(\w\)/\U\1/' | \
	sort | uniq | shuf -n $count | xargs echo | \
	tr -d ' ' | $final

What's going on here:

Nearly 30% of the American dictionary (34,242) are words with apostrophes. They could be left in to help satisfy password requirements that demand "special characters," but correcthorse isn't an algorithm that handles idiot "password best practices" well anyway. So, since every word with an apostrophe has a pair word without one, we pull 2·N words to make sure we have enough. Then we strip out the plural/possessives and capitalize every word. Then we remove duplicates and select our N words from the result. Finally, we compact that into a space-less string of words, and if the user passed the -d option, we downcase the entire thing.

Without the user options, this really could be a 1-liner; that's how it started:

alias pony="shuf -n 12 /usr/share/dict/american-english | sed 's/'\"'\"'.*//; s/^\(\w\)/\U\1/' | sort | uniq | shuf -n 6 | xargs echo | tr -d ' '"
12 points · 4 comments · view on lemmy.world

4 Comments

her01n@programming.dev · 3 pts · 1y (1 reply)

diceware is an online as well as command line implementation.

sxan@midwest.social · 2 pts · 1y

That's the one that made me make this script. I thought, surely this is a one-liner? And indeed, except that I kept adding features. I think I'm going to change my shell function back to the one-liner though. All of that extra complexity is unnecessary.

some_guy@lemmy.sdf.org · 2 pts · 1y

I opened this in a browser tab on my phone so that I can remember to review on my computer when I get home. Cheers for sharing.

some_guy@lemmy.sdf.org · 2 pts · 1y

Finally got around to reviewing this and it's surprisingly efficient. I've considered myself a pretty advanced Basher for a while and admit learning better technique from this. More specifically, I was unaware of shuf after years and years of Bash scripting. Cheers!