UPDATE: Modified for better formatting

I googled around for this but didn’t find anything. Most replies to forum posts said to use PAM, which makes sense, but here it is, created just for fun. Of course it could be much more complex (and probably a lot cleaner), but it’s a good start.

!/bin/bash
#echo "All args: ${@}"
#echo "Last arg: ${!#}"
#echo "${@}" | sed "s/${!#}//g" | tr '*' '\*'
echo "Type in what you think is a good password";
stty -echo; read PASS; stty echo
SCORE='0'

function getScore() {
if [ ${1} -eq 0 ]; then
SCORE=$((${SCORE}+${3}))
echo "${2}, +${3}"
fi
}

WEIGHT[0]='2'
CHECK[0]='^.{8,255}'
DESC[0]='At least 8 characters';
WEIGHT[1]='1'
CHECK[1]='[ABCDEFGHIJKLMNOPQRSTUVWXYZ]'
DESC[1]='Has uppercase';
WEIGHT[2]='1'
CHECK[2]='[abcdefghijklmnopqrstuvwxyz]'
DESC[2]='Has lowercase';
WEIGHT[3]='1'
CHECK[3]='[[:digit:]]'
DESC[3]='Has digits';
WEIGHT[4]='3'
CHECK[4]='[[:punct:]]'
DESC[4]='Has special characters';
WEIGHT[5]='2'
CHECK[5]='^.{12,255}'
DESC[5]='At least 12 characters';

for i in `seq 0 5`; do
echo $PASS | egrep "${CHECK[${i}]}">/dev/null 2>&1; getScore $? "${DESC[${i}]}" "${WEIGHT[${i}]}"
done
i=0; MAX=10
while [ $i -lt ${MAX} ]; do
i=$(($i+1))
if [ $i -le ${SCORE} ]; then
echo -n "*"
else
echo -n " "
fi
done
echo -e "${SCORE}/10"
echo -n "Password quality: "
if [ ${SCORE} -ge 8 ]; then
echo 'Very good, my son.'; exit
elif [ ${SCORE} -ge 5 ]; then
echo 'Getting there.'; exit
elif [ ${SCORE} -ge 2 ]; then
echo 'Kinda derpy.'; exit;
elif [ ${SCORE} -ge 0 ]; then
echo 'Whoa, terribad. Try harder.'; exit
fi