Browse: [About the FAQ Forum] [Table of Contents] [FAQs] [Contribute] [CL: Command Line Questions]
CL-10: Basic Shell Scripting
This FAQ will cover basic shell-scripting techniques in BASH (Bourne-Again SHell), the default shell on all (or at least 99%) of all current Linux distributions, and probably for many years this will remain the case.
BASH is a very powerful shell, and bash scripting can introduce users to concepts used in all computer programming, which I will talk about briefly in this FAQ.
A program is just a collection of instructions to carry out a task. Finding efficient ways to do these "tasks" is what programming is all about.
To program in BASH, you need slight knowledge of different Linux terminal commands, as that is essentially all BASH scripting is, instead of writing several commands to do a specific task, you can combine them all so they can all be done through one command with BASH scripts.
I will begin with a simple example:
Create a file called firstscript.sh, using the command
Now open that file with your favourite text editor and type the following code into the file.
echo "Hello, What is your name?"
echo "Nice to meet you, $NAME"
Now save the file. Now, before you can use this program, you must first make the file executable, you can do this like so:
chmod 0755 firstscript.sh
chmod +x firstscript.sh
Now you are free to run the program, like so:
I will go over the different lines of the program, so this will make more sense (hopefully).
#!/bin/bash - This tells the computer that the program is a BASH script.
echo "Hello, What is your name?" - "echo" prints the contents between double quotes (also known as a String Literal) to the screen
read NAME - This line introduces the concept of a "variable", a simple analogy for a variable would be a pocket, it is a storage space which can hold a variety of things, in this case the words entered by the user. In other words, The program stores anything you enter, into the variable NAME, and things can be done with that variable, which will be covered soon.
echo "Nice to meet you, $NAME" - The only new content of this line that you haven't seen before is "$NAME", as you may have found out out by running the program, when used with "echo," prints out the contents of variable NAME. The "$" can be interpreted to mean "contents/value of", so with $VARIABLE
you would be referring to the contents, or the value, stored in the variable, named VARIABLE .
Evaluating an expression can be done through the use of square brackets ([ and ]).
A simple way to explain this would be through making a rudimentary calculator, so write the code below in your favourite editor and save it as "calculator.sh"
echo "Finding X * Y"
echo "Enter X:"
echo "Enter Y:"
echo "X * Y = $X*$Y = $[X*Y]"
You can run the program by making it executable as shown before, and executing it. (./calculator.sh).
As you can see, the $[X*Y] returns the value by multiplying the values stored in the variables X and Y. You should take note that if you have many variables, you should use parenthesis '(' and ')' to show the order you want the expressions evaluated. As an example:
"$[((X*Y) / (X + Y)) - X]"
As you should know from maths, the contents of the brackets will be evaluated first.
If and Else Statements
If and else statements are useful in the way that you can get a certain block of code to be used only if a condition is true.
To show this as an example, make a new file called "ifandelse.sh", you can copy the code from "calculator.sh" to take a slight shortcut, and modify the file to look as it is below:
echo "Finding the greater number"
echo "Enter X:"
echo "Enter Y:"
if test "$X" -gt "$Y"; then
echo "$X is greater than $Y"
elif test "$X" -lt "$Y"; then
echo "$X is less than $Y"
echo "$X is equal to $Y"
A few new things were introduced in this script, and I'll go over each.
The "if" statement - This tests if the "expressions next to it are true, I'll cover these soon. and if thy are true, the code under them will be "used". After that code has been executed, the script continues from after the "fi" statement.
test "$X" -gt "$Y" - This uses the GNU command "test" and tests if the value stored in X is greater than (-gt) the value stored in Y.
The wonderous semicolon ( ; ) - Like many programming languages, BASH can use the semicolon to separate statements (NOTE: The semicolon is only needed in BASH if you have more than one statement/command on the same line, otherwise it is optional, unlike many other languages where a semicolon is needed to separate every statement.).
then - This statement is used after "if" and "elif" (It is not used anywhere else.) to tell it to use the code under the statement, if the condition is true. An easy way to think what this code means if test "$X" -gt "$Y"; then
echo "$X is greater than $Y"
is "If X is greater than Y, "then" print the contents of the double quotes in the echo statement to the screen.
elif - (short for "else if") This tests another condition if the previous condition was found as false, if the previous condition was found as true, this elif statement, and the rest of the code until after the "fi" statement, is ignored. If the condition here is found true, the code below it is executed (as with the "if" statement).
-lt - (less than) This is another argument to the "test" command that tests if a the value stored in a variable is less than another. You can find out about the different options that the test command offers you by using the command "man test"
else - This is used to test the last condition between the "if" and "fi" statements. As you can see, "then" isn't needed after the else statement.
fi - This shows the end of the if/else statements.
Looping with "while" statements
Usually, "program flow" in a shell script goes in the order "top to bottom". If you want a certain piece of code to be used a certain amount of times, there are a few different statements you can use, this part of the FAQ will cover the "while" statement.
The way the computer uses "while" statements is like so:
A good example is getting the computer to show you that it can count up to ten. So create a file called "while.sh", and write the following code into it:
while test "$X" -le "10"
If you run the script you will get the following output:
As you can see, using loops (with "while" statements in this case) is much more efficient than writing 10 different "echo" statements to get exactly the same output.
Loops are a very important part of all programming and most programs that you will ever write are very likely to contain at least one loop.
As with other examples, this one also introduced new ideas.
X=1 - This stores the value "1" in the variable named X, quite simple. NOTE: You cannot have spaces between X and the equals sign ( = ), and the equals sign and 1, otherwise they are all treated as separate statements.
while - As said before, this is used like "while condition is true, execute/process code between the "do" and "done" statements.
-le - (less than or equal to) Tests if one expression/value is less than or equal to another.
do - If the condition in the while statement was true, the do statement shows where to start processing the code. "do" is used with while, until and for statements. (both of which will be explained shortly.)
X=$[X+1] - This increments the value stored in variable X by one every time this code is encountered.
done - As said before, this shows the end of the "while" statement. Behaves in much the same way as "fi" does for if/else statements.
Exercise: Now you can try making a script that counts down from 10 to one using your gained knowledge of shell scripting. If you really want, you can even send me a PM and I'll mark it for you ;).
The "until" loop
Something that uses the opposite logic of "while", but has the same syntax is the "until" statement which is quite self-explanatory, though i will provide an example anyway.
until test "$X" -gt "10"
This executes the code between "do" and "done" until the value stored in the variable X is greater than 10. This script has the same output as the previous example.
The "for" loop
"for" loops have quite a different syntax from that of "while" and "until" loops. The best way to explain these differences is by example, so create a file "forloop.sh", And write the following code into it:
NOTE: The code below contains only my opinion, I mean no offence to anybody whatsoever, if you don't agree with it you can substitute values for your tastes.
for food in chinese italian korean vietnamese japanese thai cambodian
echo "$food food tastes good"
echo "But indian food does not"
I will go over the new parts in this script.
for - "for" statements have the syntax "for <variable> in <variable value> ...". I will explain parts of this now. <variable> you substitute for the name of a variable you want to access/use inside the for loop. "in" stores the strings and/or values after it into <variable>. <variable name> are the values or strings that you want <variable> to store. For example, the first time through the last "for" loop, the value stored in the variable food would be the string "chinese", the second time through, "italian" and so on. The value of <variable> is one of the strings/numbers after "in" each time through the loop. The loop finishes when all of the numbers/strings after "in" have been used. If you are confused over what was just said (I wouldn't be surprised), you should run the script and the code should be understood quite easily.
The alternative "for" syntax
If you have ever come across some programming in C or C++, you are likely to have seen that the syntax of the "for" statement is quite different to what has been shown in the previous examples. This other way of using for loops will be introduced now:
for (( i=0; i<10; i++ ))
For loops contain three parts, each one separated by semicolons. The format of this is:
I will explain each part now:
initialisation - This part creates, and sets the value for one or more variables. In the above example, "i = 0" Creates the variable 'i' if not previously created, and sets the value that 'i' contains, to zero.
condition - This part tests one or more conditions, just like the if/while statements do. Using the above as an example: "i<10" would test if the value stored in 'i' is less than ten. If it is, the loop will run, if not, the loop will be ignored.
increment - This part is used to alter the variable(s) that were previously created. In the previous case "i++", The value stored in 'i' is incremented by one each time the loop has run through.
A new thing that you may have noticed is the increment operator (++). This will increment the value stored in a variable by one. There is also a decrement operator that can be used (--), which will decrement a value by one.
Time for a proper example of it's use, note that the output will look familiar.
for ((i=0, f = 10; i<10, f > 5; i++, f--)); do echo $i;done
This certainly isn't the most efficient for loop, but it demonstrates what they can do quite well.
It can be "read" as saying, "Initialise 'i' as 0 and 'f' as 10, while 'i' is less than 10 and 'f' is greater than 5, carry out the loop (printing each value of 'i' to the screen) between the 'do' and 'done' statements, and at the end of each "loop", to increment 'i' by one, and decrement 'f' by one." The loop will give the following output:
The "seq" command
This command prints out a sequence of numbers, and as quoted from the "seq" man page, takes these arguments.
I'll give an example of each use, even though they are quite easy to understand.
That would print out the numbers 1, to 20, being incremented by 1 each time. Though if you are wanting the numbers to count up starting from 0, you will need to use the one of the last two formats of the "seq" command, as shown below.
seq 0 20
That would display the numbers from 0 to 20, again incrementing by one each time.
If you want to change the amount incremented, you will have to use the third format of the seq command, for example:
seq 0 3 50
This would display the numbers one through to 50 with an increment of three each time (as compared to the others where "seq" only incremented by 1 each time.
Counting down with the "seq" command is also possible, to do this, you would have a negative "INCREMENT", prefixing the number with a "-", like so:
seq 400 -20 5
This would count down from 400 with a decrement of 20 until the number 5 is reached, as you will be able to see from these examples, "seq" is very easy to use, and you can find out a little more about it from it's man page. "seq" can be used in your shell scripts like all other commands, and as you may see, is much more efficient than any loop to do the same task.
Thanks to aru for telling me about the seq command and the ability of using C's syntax in for loops.
If you have any ideas, comments etc. for this FAQ, you can PM me.