In this tutorial you will learn the basic syntax of Bash. This is also useful for other UNIX shells.

In the following examples we can use $ to distinguish a command from its output.

Table of Contents

Script structure

  • It’s recommended to put in the first line the “shebang” (#!) followed by the location of the Shell interpreter you want to use.
    #!/bin/bash
    
  • Script files need to have execute permissions (and read permissions as well).
    chmod +x script.sh
    

exit

exit terminate the script. You can use it without parameters (same as exit 0 or not adding exit) or you can add the exit status as a parameter.

  • exit 0: means the program has terminated sucessfully.
  • exit $?: terminate with the exit status of the last command.
  • exit <any positive number in the range [1..255]>: program has terminated with an error (exit status <number>). There are some reserved exit codes (https://tldp.org/LDP/abs/html/exitcodes.html) but you can define your own exit codes.

Variables

x=6
item="some text"
  • Do not add spaces between =.

Reference a variable using $ and its name (or ${varname}). You can type the variable inside double quotes, but if you use single quotes, command will take the variable name as text.

$ item="some text"
$ echo $item
some text
$ echo ${item}
some text
$ echo "$item"
some text
$ echo '$item'
$item

You can echo the output of a command (or do whatever you want with it) by using `COMMAND` or $(COMMAND).

$ echo date
date
$ echo `date`
vie 01 oct 2021 18:45:13 CEST
$ echo $(date)
vie 01 oct 2021 18:45:15 CEST

If you want to output a text with several lines, you can use echo -e, printf or use quotes.

y="One Line\nSecond Line"
printf $y
$ echo "hello
bye"

In some cases, you can also preserve newlines by referencing the variable like this: "${var}":

y=`cat file.csv`
echo "${y}"
echo "$(ls -l)"

Unset (delete) a variable with unset.

unset y

Working with text

${var:start:character_number}: select a substring of ‘var’ of ‘character_number’, starting from index ‘start’.

$ a="text";echo ${a:0:2}
te
$ a="text";echo ${a:1}
ext
$ a="text";echo ${a::1}
t
$ a="pass";echo ${a:(-1)}
s

${var/pattern/replace}: search ‘pattern’ in ‘var’ and replace with ‘replace’.

$ a="text";echo ${a/t/r}
rext
$ a="text";echo ${a//t/r}
rexr
$ a="text";echo ${a/t}
ext

Arrays

x=(3 5 9)
y=(some_word, "some sentence")

echo ${x[0]}

x[0]=6

echo ${x[0]}

$ ./script.sh
3
6
  • Print all items in an array.
    echo ${x[@]}
    
  • Print the number of items in an array.
    echo ${#x[@]}
    

Operators

Arithmetic

+ - * /
  • %: modulus (remainder of a division).
  • **: power operator.
  • x++: increase x by one.
$ echo $((5 + 8))
13

Bolean

  • Strings.
    =
    ==
    !=
    -z #test if a string is null
    -n #test if a string is not null
    -e #test if a file exists
    
  • Numbers (if you use [ ] to enclose the condition).
    • -eq: equal to.
    • -gt: greater than.
    • -ge: greater than or equal to.
    • -lt: less than.
    • -le: less than or equal to.
    • -ne: not equal to.

Conditionals

if, elif, else

Basic structure:

if [ EXPRESSION ]
then COMMAND
else COMMAND
fi
  • EXPRESSION is usually enclosed in brackets [ ], but you can use a command (the first bracket [ is a shortcut for the test command).
    if [ $x -eq 6 ]
    
    if test $x -eq 6
    
  • If you add then in the same line as if, you must use a semicolon.
    if [ $x -eq 6 ];then
    
if [ $x -eq 6 ]
then echo "x is equal to 6"
else echo "x is not equal to 6"
fi

# or
if [ $x -eq 6 ]
then
echo "x is equal to 6"
else
echo "x is not equal to 6"
fi

# or
if (($x == 6))
then
echo "x is equal to 6
else
echo "x is not equal to 6"
fi
if [ $y = "house" ]
then
echo "y is equal to house"
elif [ $y = "office" ]
then
echo "y is equal to office"
else
echo "y is not equal to house or office"
fi

You can also use this structure for simple conditionals:

[ $x -eq 6 ] && echo "x is equal to 6" || echo "x is not equal to 6"

Use double brackets ([[ ]]) when you need to use the AND (&&) and OR (||) operators.

if [[ $x -gt 6 && $x -lt 9 ]]
then
echo "x is greater than 6 but less than 9
fi

Note that you need to add spaces between the operator in all cases.

Curly braces: {}

You can use {} to build an array or a range, to expanse a parameter or to group command outputs.

$ echo {1..5}
1 2 3 4 5
$ touch ABC_{1..20}.txt
$ ls
ABC_10.txt  ABC_12.txt  ABC_14.txt  ABC_16.txt  ABC_18.txt
ABC_1.txt   ABC_2.txt  ABC_4.txt  ABC_6.txt  ABC_8.txt
ABC_11.txt  ABC_13.txt  ABC_15.txt  ABC_17.txt  ABC_19.txt
ABC_20.txt  ABC_3.txt  ABC_5.txt  ABC_7.txt  ABC_9.txt

Loops

for

for i in $some_array
do
echo $i
done
for i in {1..30}
do
[ if $i = 15 ]
then break
# this will stop the loop, use 'continue' instead of 'break' to jump to the next loop item
fi
echo $i
done

while

i=5
while [ $i -gt 0 ]
do
echo $i
i=$((i - 1))
done

case

case $x in
3) echo "x is equal to 3";;
6) echo "x is equal to 6";;
*) echo "x is not equal to 3 or 6";;
esac
case $1 in
"") echo "No parameters"
exit 1;;
some_parameter) echo $1;;
*) echo "Parameter is not 'some parameter'
exit 1;;
esac

select

PS3="Select the item: "

select item in "i1" "i2" "i3"
do echo "You've selected $item"
break
done

Functions

Definition

Function definition must precede invocation.

function_name(){
command1
command2
}
# In one line, remember to add a semicolon after the last command
function_name() { command1; command1; }

Invocation

function_name

Function arguments

You can pass arguments to functions.

fun(){
  if [ -n $1 ]
  then
    echo $1
  fi
}

fun arg1

To pass an script argument to a function, you must invocate the function with that argument.

# ./script.sh arg1

fun(){
  if [ -z $1 ]
  then
    echo "No argument passed."
  else
    echo $1
  fi
}

fun $1

Script parameters

./script.sh arg1 arg2

  • You can access these arguments using $ and 1 for the first argument, 2 for the second, etc.
    #!/bin/bash
    if [ -n $1 ]
    then
    first_argument=$1
    echo $first_argument
    fi
    
    $ ./script.sh my_argument
    my_argument
    

Some characters have special meanings (referring to parameters):

There are several ways to loop between the parameters:

while [ $# -gt 0 ];do
  case $1 in
    -e) echo "Found 'e' parameter";;
    -config) echo "Found 'config' parameter"
    CONFVALUE=$2
    shift #Delete first argument and move the second to first place, third to second place, etc.
    if [ $CONFVALUE -gt 10 ];then
      echo "Error: Config value must be less than 10"
      exit 1
    fi
    ;;
  esac
  shift
done
for arg in [email protected]; do
  case $arg in
    -a) echo "Found 'a' parameter";;
    -b) echo "Found 'b' parameter;;
    *) echo "Unknown parameter;exit 1;;
  esac
done
Test with this online terminal: