Shell scripting basics

How to automate the shell using scripts

view on github

Write shell scripts

Table of contents

  1. Overview
  2. Control flow
  3. Functions
  4. Operators
  5. User input

Overview

Running shell scripts

  • Any command that can be executed from the shell may be placed into a script and behave exactly the same (and vice versa).
  • A script must have the execute permission x set for the current user before it may be run.
  • Important : script started from the command line doesn't run in the current shell process : a new shell is started and runs the script instead.
  • A notable exception to the above is what is called "sourced scripts".

Writing shell scripts

  • The first line of any shell script has to be the shebang #! followed by the path to interpreter.
  • That line identifies the interpreter to use and should never contain any additional character.
  • Shell comments are prefixed with #.
#!/bin/bash
# here's a comment
echo "here's a script"

Note : bash scripts are particularly picky when it comes to formatting. Make sure spaces are put where they are needed and not put when they are not needed.

Using vi as an editor

  • There are two modes in vi : insert mode and edit mode.
  • In insert mode you may input or enter content into the file.
  • In edit mode you can move around the file and perform actions such as deleting, copying, search and replace, saving etc...
  • vi regexp uses Vim syntax.

Control flow

test expressions

  • Built in control structures in the shell are more or less the same as in any other programming language.
  • They differ in that the expressions used do not evaluate through built-in operators, but are based on test expressions instead.
  • Those expressions can perform various tests on variables, files, etc ... as seen below.

Control structures

  • if conditional structure :
# if a file exists in my home directory
if [ -f "$HOME/myfile" ]; then
   # do something
fi
  • while loop structure :
# as long as a variable is greater than zero
while [ "$counter" -gt 0 ]; do
   # do something
done
  • until loop structure :
# as long as a variable is different than zero
until [ "$counter" -eq 0 ]; do
   # do something
done
  • for loop structure :
# execute a sequence of instructions for each value in a list or an array
# $list is not quoted so the loop processes the results of word expansion
for value in $list; do
   # reference the value inside the loop by using $value ...
done
  • case conditional structure :
case "$var" in
   # if $var equals value1 ...
   "value1")
      # do something
      ;;
   # if $var equals value2 ...
   "value2")
      # do something
      ;;
   # if $var is different ...
   *)
      # do something
      ;;
esac

Caveats

  • When using the bash shell, it's best to wrap expressions in double brackets (although single brackets work too)
  • One of the most useful applications of for loops is the processing of a set of files (wildcards and shell globbing allow that).
  • break and continue keywords are available in bash loops, as they are in many other languages to the same effect.

Functions

  • Shell functions accept a list of words as argument so as multiple parameters can be passed.
function some_function {
   # variable local to a function are not accessible from outside
   local some_variable="function received $# arguments"
   # do something
   echo "$some_variable"
}

# call the function and pass a word list as argument
some_function some arguments and more for a total of 9
  • Function parameters are accessible within the function as $1, $2, etc ... like in a normal script.
  • The function definition must appear in the script before it is called.
  • Shell functions do no return values but exit codes like any other linux process.
  • Workarounds to retrieve values from functions exist, such as :
function sample_function {
   # print return value to the function's stdout
   echo "function actual return value" > /dev/stdout
   # "return" a success code
   return 0
}

# use command substitution to read the return value
result=$(sample_function)

Operators

  • Type let --help to view the list of supported arithmetic, logical and bitwise operators.
  • Evaluation of expressions that use operators can be performed in 2 ways :
# evaluate an expression and store the result in a variable
let var="4 + 2"

# prints 6
echo "$var"

# wrap the expression in parentheses and use command substitution
echo $((5 != 3))
# prints 1 for true
  • ${#var} returns the length of a variable.

User input

  • User input can be processed by the shell using the read command.
  • read prompts user for input and then assigns the input values to variables :
# ask for user name, first name and employment
echo "Please enter your name and first name:"
read -r lname fname
echo "Please enter your profession:"
read -r empl
echo "$lname $fname works as $empl"
  • User input is processed as a list of words, each word being assigned to the variables passed as arguments to read.
  • If there are more words than variables, remaining words are all added to the last variable.
  • If there are less words than variables, remaining variable are set to blank or null.
  • read comes with a variety of options (for instance -p to specify a prompt and -s to make the input silent).