My first bash script
Published: 2023-04-18 01:24:42

I started learning how to code about a month and a half back. Joined a full-stack web development coding bootcamp. Got introduced to the basics of bash scripting. And was encouraged to learn more on my own. So I picked the following problem and wanted to write a bash script to solve it: Write a bash script to check and validate passwords. An acceptable password must be:

- No less than 8 and no more than 16 characters long
- Must have at least one lowercase and one uppercase characters
- Must have at least one numeric character
- Must contain one of "#,@,$,%,*,+,-,="

Now I've seen how the create and enter password sequence works on Linux-based systems. Typically, there's a text that prompts you to enter a password. So, that became the first line of my script (after shebang, of course):

echo "Enter new password:"

The user is required to enter their password after this line. And I had to recreate it. How? From NetworkChuck's YouTube videos, I knew that somehow the read command had to be used. But the user input can't be shown on the console. So, the read command had to be used with the '-s' flag. That gave me my second line:

read -s password

And when a user enters a password, the program should start validating the input against the minimum requirements.

First things first. If a user enters less than 8 characters, the program should tell them that they must do better. The conditional in which I understood the use case gave away what I should do to implement it in the script: an if-then statement:

if [ ${#password} -ge 8 ]; then

If the input matches the requirement, what must the program do? I must evaluate the input further, validating it against the rest of the requirements, one after another:

if [ ${#password} -ge 8 ]; then
	if [ ${#password} -le 16 ]; then
		if [[ ${password} =~ [a-z] ]]; then
			if [[ ${password} =~ [A-Z] ]]; then
				if [[ ${password} =~ [0-9] ]]; then
					if [[ ${password} =~ [#,@,$,%,*,+,-,=] ]]; then
					echo "Password created"

But what if doesn't meet one of these requirements. I had to throw in feedback to the user why it didn't work. And I had to account for all possible cases:

else echo "Must contain at least one of: #, @, $, %, *, +, -, ="
					fi
				else echo "Must contain at least one numeric char"
				fi
			else echo "Must contain at least one uppercase char"
			fi
		else echo "Must contain at least one lowercase char"
		fi
	else echo "Can't be longer than 16 chars"
	fi
else echo "Must be at least 8 chars long"

fi

And there you go. I tasted success! Couldn't wait to try it out.

So, I saved my changes (I used the nano editor to author the script). Made the script an executable. And entered the command: bash password.sh

And there! My labor had already borne fruits. Never before did Enter a password on the screen look this beautiful!

I entered a password that wasn't 8 characters long and pressed Enter.

Wow! "Password must be at least 8 characters long" - Now I wasn't a mere consumer any longer. This was my first step as a producer. Soon I would be producing solutions to really complex prob...

My castle fell apart prematurely. The program exited immediately after providing feedback. I ran the program again and again to check whether it looks for all the specified conditions. And that it does. But that's not good enough. The program must not exit when a user input doesn't match a condition. It should inform the user and prompt them to enter a password again. Now, that's not how I visualized the problem at the outset. Also, even that's not enough. The script needs to be refactored to make sure that the user is consistently prompted to enter a password until all conditions match. This requires some sort of a looping mechanism. Which I've been trying to incorporate into my script but haven't been able to succeed yet. Here's what my script looks like now and I am looking for pointers: where did I go wrong?

#!/bin/bash

echo "Enter new password:"

read -s password

while [ ${password} != "" ]
do
	if [ ${#password} -ge 8 ]; then
		if [ ${#password} -le 16 ]; then
			if [[ ${password} =~ [a-z] ]]; then
				if [[ ${password} =~ [A-Z] ]]; then
					if [[ ${password} =~ [0-9] ]]; then
						if [[ ${password} =~ [#,@,$,%,*,+,-,=] ]]; then
							echo "Password created"
						else 
							while ! [[ ${password} =~ [#,@,$,%,*,+,-,=] ]]
							do
							{
								echo "Must contain at least one of: #, @, $, %, *, +, -, =";
								echo "Enter new password:";
								read -s password;
							}
							done
						fi
					else 
						while ! [ ${password} =~ [0-9] ]
						do
						{
							echo "Must contain at least one numeric char";
							echo "Enter new password:";
							read -s password;
						}
						done
					fi
				else 
					while ! [ ${password} =~ [#,@,$,%,*,+,-,=] ]
	                                do
	                                {
		                                echo "Must contain at least one uppercase char";
		                                echo "Enter password:";
		                                read -s password;
	                                }
	                                done
				fi
			else
				while ! [ ${passwoord} =~ [a-z] ]
				do 
				{
					echo "Must contain at least one lowercase char";
					echo "Enter password:";
					read -s password;
				}
				done
			fi
		else 
			while [ ${#password} -gt 16 ]
			do
			{
				echo "Can't be longer than 16 chars";
				echo "Enter password:";
				read -s password;
			}
			done
		fi
	else 
		while [ ${#password} -lt 8 ]
		do
		{
			echo "Must be at least 8 chars long";
			echo "Enter password:";
			read -s password;
		}
		done
	fi
done