Scripting Fundamentals - Learning if/then in bash
Welcome to another series - "Scripts and How They Got There", where I break down some of the scripts I run locally and how they evolved from rudimentary commands into their current state. If you want to look over this script (or my other bash scripts), please feel free to grab a copy from my Github page.
Learning if/then loops for bash
I like to try and make some practical use of learning exercises, so when it came time in my studying to learn how to configure if/then statements for bash, I wanted to write something more functional than echoing "fizz" or "buzz" based on an input condition, so I worked out an interactive script for folder creation. It is fairly straightforward, and handles some basic permission checks. If the user text is cleaned up, this could easily be "snipped" into a larger script meant for production which includes a manual folder creation (with permission-based failsafes included).
Time to Script
Let's start with the overall goal/structure of the script. The overall goal is to prompt the user for a new directory, check to confirm the user has appropriate permissions to create that directory, and if they are permitted, create the directory and bring the user there.
Here’s our rough draft in "storyboard code":
Request desired directory path from user (store into variable)
Check for existing directory with same filepath (or warn user & quit)
Check for write permissions to establish the desired filepath (or warn user & quit)
Create directory, navigate user to directory
confirm location for user
Seems straightforward enough? Let's break it down further. Step 1 is straightforward; bash has a built-in command to import data from user input. We establish a variable to use as the desired directory path, I'll call it DIRname because I lack creativity and like to understand my code when coming back to it in the future.
#Declare a string variable called "DIRname"
declare -l DIRname
echo "Please enter desired directory (full path please):"
read DIRname
Testing for specific conditions
Terrific. Now we have the varaible we need to work the rest of the script. The first thing we need to check is whether or not there is already a directory named whatever the user has put in.
if [[ -e $DIRname ]]
then echo "Directory called $DIRname already exists, dingus. Now closing program."
exit 1
...
That was easy, but you may have noticed that we have not “closed” the if-statement yet, nor do we have an “else” command. That’s because we are going to test for a second condition if our first test passes (i.e. if the directory entered does NOT exist). Here let’s use the “else” section to include another test of our variable $DIRname. To save time and CPU processing, we only want to test for write permissions if the user enters an acceptable directory, so there is no sense in checking for write permissions if the user entered an existing directory. Thankfully, we can just bury another if-statement inside our “parent” test statement to check for write permissions. For the “else” clause of our condition test, we add another simple if-statement, this time checking user permissions against the value of $DIRname.
...
else if [[ -w $PWD ]]
then mkdir $DIRname && cd $DIRname
echo "Great job, dingus. Directory created."
else
echo "You do not have permission to create directories here, dingus. now closing program."
exit 2
fi #this closes our “child” if-statement
fi #this closes the “parent” if-statement
I like to structure my if/then tests by using tabs, to more easily see where I may be missing a terminating 'fi' or additional 'else' or 'then' somewhere. Here is a simplification of we structured this nesting “if-doll” - Looking down the left-hand side, you'll see each if-statement is comprised of three parts:
if [[condition0]]
then {code}
else {if [[condition1]]
then {code}
else {code}
fi
}
fi
As confusing as it may seem, the "else if" in the loop is just another if-statement, structured exactly the same way. Separating it (as opposed to testing for it with condition0) allows us to save compute power & RAM by testing for conditions in a logical order. For your own uses/purposes, there is no upper limit (beyond your patience) for how many if-statements you can nest inside of each other, so go have fun!
Final Thoughts & Disclaimers
All in all, the script is very rudimentary, and does not include any failsafes for re-entering text. This is not meant to be a replacement for GUI directory making, and frankly the mkdir command built into bash is far superior to this script. What I hope you learned here is a little bit about if/then loops and how they can interact with each other to test for simple conditions or a stack of conditions, one at a time.
Thanks for reading this far.