A particular barrier keeping me from writing my own shell scripts for a long time was that I didn’t know how to run, or execute, them. At the time, this seemed like something obvious that I should know, and I felt ashamed. Now, I know that, depending on how someone has arrived at programming, this information might not be obvious at all e.g. for folks like me, who entered programming through front-end development and never formally studied computer science, I suspect this is not obvious.
In the spirit of writing the blog post I wish I found, here is how to write and run a shell script, followed by an explanation of the script written for readers who are brand new to shell scripting. Feel free to skip around this post as you please.
In this post, I assume that readers have the following knowledge:
- An idea of what it means to run, or execute, a script (a relevant talk by Susie Grange about teaching concepts like “run”)
- Ability to
cdinto a directory from the command line
Steps to write and run a shell script
- Create a new file in a location that is easy to access (e.g. a directory where you save coding projects)
- Name it
example.sh(shell scripts use the
- In the file, add the following:
echo "Hello, $NAME!"
- Open a command prompt (i.e. Terminal)
cdto the directory where you created the file in Step 1.
- Run the command
sh example.sh Lara(notice the
shbefore the file path)
- You should see the output, “Hello, Lara!”
Shell – A shell is a program that allows a user to interact with the operating system. It’s called a shell because it’s “built around” the inner part of the operating system, often called the kernel. The console in the browser developer tools can be seen as a shell for the browser.
Bash – Bash is a Unix shell and scripting language, accessible in the command line (i.e. the Terminal or abbreviated CLI). Mac operating systems are based on Unix, so this is usually the shell that opens by default in the Terminal on a Mac.
Shell script – A shell script is a program, usually written in a scripting language, that is run by a shell. It might be as simple as a sequence of commands that are commonly run together, or it could include logic, functions, API requests, and more.
Shebang – The syntax
#! is called a shebang. A shell script must begin with this syntax so the machine knows which language you are using for your script. The
#! is followed by the path to the interpreter for the scripting language. For bash (on Unix operating systems), this is
Explanation of our script
In the steps above, we added the following to our shell script,
echo "Hello, $NAME!"
Notice the shebang at the top of the file.
If your script was written in another language, for example, Node.js, the file would be named
example.js and the shebang would point to a different interpreter:
Notice the slight difference in the paths to each interpreter (
node). What differences do you notice, and what do you think they mean?
Now, read the next two lines of our script after the shebang:
echo "Hello, $NAME!"
Recall how we ran our script and what the output was (note that the
$ at the beginning of the following lines indicates we are using the command line):
$ sh example.sh Lara
What do you think
$1 is doing in our script? Let’s expand the script a bit more:
echo "Hello, $FIRST_NAME $LAST_NAME!"
Now, let’s run the script a couple of times:
$ sh example.sh Lara Schenck
Hello, Lara Schenck!
$ sh example.sh Rajanraj Siwakoti
Hello, Rajanraj Siwakoti!
Looking at these two blocks of code – the script, and the output when it is run – what do you think
Stare at it until it makes sense.
This is some of my favorite programming advice. I read it in a book ironically titled Zero Bugs and Program Faster by Kate Thompson. She writes about how our brains are wonderful at recognizing patterns – code is full of patterns, so one way to learn new programming skills is to read the code and allow your brain to make the connections. Sometimes this means stepping away for a while, forgetting about it, then coming back. Sometimes we try too hard when what we really need to do is get out of our own way – I did not understand that earlier in my career, and it’s still hard to do.
Why create a shell script?
npm dependencies. Often, these are scripts run through
npm and registered in package.json’s
scripts object. As commands become more complex, using package.json to lump several commands into a single script entry can become cumbersome, and it is difficult to use any logic or data. A shell script can be used to store these commands in their own file where you may use logic and any control structures (i.e.
for loops) supported by the scripting language.
These scripts can be useful for a wide variety of contexts, not just running front-end scripts. For example, a specific use case I came across at my job was when I needed to run several commands to deploy code to a staging environment. At the time, this needed to be done for about 25 environments. Every time I had to do the task, I would forget what I did before and have to figure it out all over again. Storing these commands as a shell script was a nice way 1) to run several commands with a single command, and 2) to record the steps I took to accomplish the task so that I could do it more easily next time.
Learning shell scripting is a powerful tool in your workflow, and it can be a way to increase your confidence using the command line.
In this article, we will only be looking at Bash scripts. A couple of reasons why I like Bash for authoring shell scripts that interact with the file system (e.g. copying, renaming, or deleting files and folders):
- It is installed by default on Unix machines which, in my experience, is usually the operating system used on an external server (i.e. using
sshto access the command line on another computer). So, if your computer and a server are both Unix, the Bash knowledge applies to both.
- Bash is a declarative language specifically created for shell scripting, meaning there is common functionality built into the language. For example, in Node.js you need to require a module to rename a file, in Bash, that functionality is part of the language via the