When we start to learn the command-line interface, we generally learn and explore it interactively. That is, we enter one command at a time so that we can see the results of each command.
Here is a GIF of me using the command line to explore a directory of Shakespearean plays, counting the number of words and the number of times the word "murder" appears, both in King Lear and in all of Shakespeare's plays:
Using the command-line interface in this interactive fashion is fine, when trying things out. However, as you've likely noticed, typing is a very error-prone activity. So for complex tasks that we want to repeat, the best practice is not to retype their code from the beginning, but to create a self-contained shell script that can be run as a one-liner.
Let's start off with something easy. Make a junk directory somewhere, such as
/tmp/my-playground and change into it – we don't need to litter our actual workspace with test code.
A shell script is nothing more than a text file, which should make sense, as all of our command-line scripting has so far been, well, text.
Let's use the nano text editor to create a shell script named
hello.sh. Follow these steps:
nano should open up and present an empty file for you to work in. Type in the shell command:
echo "Hello world"
hello.sh. Hit Enter to confirm this.
hello.sh script with this command:
Here's what the steps look like as a GIF:
hello.sh is not very impressive, but it captures the gist of what we want to do: wrap up a series of commands into a file, i.e. a script, so that we can re-run that script as much as we'd like.
We not only eliminate the prospect of typographic errors that occur when retyping commands, we also open up the door to making the script reusable in different contexts.
hello.sh more complicated. Instead of just echoing
Hello world, let's design the script so that it will say
Hello to a specific value (i.e. someone's name). And we'll make the script sound more excited.
Here's the proposed usage:
bash hello.sh Dan
And here's a GIF:
First of all, how do we customize
echo "Hello world"? By replacing
world with a variable. Let's try it interactively from the command-line:
yourname=Dan echo "Hello $yourname"
So the question is: how do we get the
hello.sh script to read in the argument (in this case, someone's name) that we pass into it?
bash hello.sh George
We do this via a special variable in bash. The variables,
$3 (and so on), refer to the first, second, and third arguments that were passed into the script from the command line.
Thus, in the above example,
George will be stored in the variable
hello.sh begins running.
nano and change the code to this:
$yourname=$1 echo "Hello $yourname"
Save the changes and run
bash hello.sh Mary to see how the output changes.
Want to return the output in all caps? Then modify
hello.sh like so, piping the output through tr to replace lowercase letters with uppercase letters:
$yourname=$1 echo "Hello $yourname" | tr '[[:lower:]]' '[[:upper:]]'
And if you want to be concise, you've probably noticed that the variable,
$yourname, isn't really needed. The code could be simplified to this:
echo "Hello $1" | tr '[[:lower:]]' '[[:upper:]]'
Time to slow down. If you can make a script that you can execute like this:
Then you have already learn a major concept. At the very least, you have learned the method by which programmers stuff a bunch of complicated into a "container" that anyone else can run in a single line.
In the next tutorial in this series, I've taken this same idea except to go more indepth in making a script "reusable". Do you need to make a reusable script, right now? Do you even know what "reusable" means? If not, then you don't need to read that tutorial, just yet.