overview edit doc new doc remove

Jan 26, 2018

Bash scripting

Bash is a Unix shell and command language written by Brian Fox for the GNU Project as a free software replacement for the Bourne shell. First released in 1989, it has been distributed widely as the default shell for Linux distributions and Apple's macOS (formerly OS X). Bash stands for Bourne again shell.

Basics

A shell script is conventionally saved with a .sh extension, in this script you should write a shebang at the top of your script indicating that you want to run it as a bash shell script. This shebang exists out of #! followed by an interpreter, in this case it's the absolute path to bash: /bin/bash. This shebang's purpose is to let your current shell know which interpreter it needs to call when you will execute it within your shell. The execution can be done by giving the file execution rights for the user; chmod +x script.sh and you can run this script by doing:

$ ./script.sh

Syntax

Comments

Comments in Bash are preceded by a #.

# comment

Use of Backslash

A \ split commands on several lines.

ls -l \
   --reverse \
   --human-readable \
   --full-time

[[(({}))]]

Brackets are the syntax for the POSIX test command. Double brackets on the other hand are the syntax for the bash conditional expressions but more powerful then the POSIX one. They have an extra functions, they allow the use of regex and operators like || and &&. Single parentheses are used to create subshells where double parentheses are used for arithmetic expressions. Curly brackets don't have a really specific function however they are usefull if you want to expand variables and use variables in strings or in other variables.

#! /bin/bash

# []
#while [  $COUNTER -lt 10 ]

#[[]]
if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi

# ()
echo $(ps -ah)

# (())
echo $((a + b + (14 * c)))

# {}
foo="foot"
echo "${foo}ball"

Quotes

Double quotes will change the call to the variable into the value. Single quotes will literally echo what you typed including references to variables. Back quotes are used to execute commands, it could be compared to the use of subshells.

#! /bin/bash

MYVAR=sometext

#""
echo "double quotes gives you $MYVAR"
# output: double quotes gives you sometext

#''
echo 'single quotes gives you $MYVAR'
# output: single quotes gives you $MYVAR

#``
filepath=`pwd`

Datatypes

The shell treats all variables as strings. Local variables aren't available outside of a function.

#! /bin/bash

name="Sebastiaan"

demLocal () {

  local name="Paul"
  return

}

If else

A condition is placed within single of double brackets. A space is needed between the brackets and the conditions on both sides. Integer comparisons can be done with: eq, ne, le, lt, ge and gt. It is also possible to test if a file exists, permissions, file equality, and so on, checkout man test for more information and examples or check below.

#! /bin/bash

if [ $age -ge 16 ]; then

  echo "You can drive"

elif [ $age -eq 15 ]; then

  echo "You can drive next year"

else

  echo "You can't drive"

fi # close the if statement

# you can also use logical operators like &&, || and !
if (( ((num > 0)) && ((num < 11)) )); then

  echo "$num is between 1 and 10"

fi

# if samp_dir doesn't exist make it
[ -d samp_dir ] || mkdir samp_dir

# test if a string is null
if [ "$str1" ]; then

  echo "$str1 is not null"

fi

# check for equality
if [ "$str2" == "$str3" ]; then

  echo "$str2 equals $str3"

elif [ "$str2" != "$str3" ]; then

  echo "$str2 is not equal to $str3"

fi

if [ "$str2" > "$str3" ]; then

  echo "$str2 is greater then $str3"

elif [ "$str2" < "$str3" ]; then

  echo "$str2 is less then $str3"

fi
Checking a file
#! /bin/bash

# check the file test_file1 and test_file2
file1="./test_file1"
file2="./test_file2"

if [ -e "$file1" ]; then

  echo "$file1 exists"

fi

if [ -f "$file1" ]; then

  echo "$file1 is a normal file"

fi

if [ -r "$file1" ]; then

  echo "$file1 is readable"

fi

if [ -w "$file1" ]; then

  echo "$file1 is writable"

fi

if [ -x "$file1" ]; then

  echo "$file1 is executable"

fi

if [ -d "$file1" ]; then

  echo "$file1 is a directory"

fi

if [ -L "$file1" ]; then

  echo "$file1 is a symbolic link"

fi

if [ -p "$file1" ]; then

  echo "$file1 is a named pipe"

fi

if [ -S "$file1" ]; then

  echo "$file1 is a network socket"

fi

if [ -G "$file1" ]; then

  echo "$file1 is owned by the group"

fi

if [ -O "$file1" ]; then

  echo "$file1 is owned by the userid"

fi

Loops

Case
#! /bin/bash

read -p "How old are you : " age

#check the value of age
case $age in

  [0-4])
    echo "To young for school"
    ;; # Stop checking further

  5)
    echo "Go to kindergarten"
    ;;

  [6-9]|1[0-8])
    grade=$((age-5))
    echo "Go to grade $grade"
    ;;

  *)
    echo "Default action,You are to old for school"
    ;;

esac # End case
For
#! /bin/bash

for i in 1 2 3 4 5; do

  echo "Welcome $i times"

done
While
#! /bin/bash

COUNTER=0
while [ $COUNTER -lt 10 ]; do

  echo The counter is $COUNTER
  let COUNTER=COUNTER+1

done
Until
#! /bin/bash

COUNTER=20
until [ $COUNTER -lt 10 ]; do

  echo COUNTER $COUNTER
  let COUNTER-=1

done

Printing and scanning

It is possible to print over multiple lines with the use of cat

#! /bin/bash

cat << END
This text
prints on
many lines
END

To receivee input from the command line you can use read.

#! /bin/bash

read -p "What is your name? " name
echo "Hello $name"

To read multiple lines use:

#! /bin/bash

read -p "Enter 2 Numbers to Sum : " num1 num2
sum=$((num1+num2))
echo "$num1 + $num2 = $sum"

To hide the input text use:

#! /bin/bash

read -sp "Enter the Secret Code" secret

Random numbers

#! /bin/bash

cat /dev/random | tr -dc 'a-fA-F0-9' | fold -w 20 | head -n 1

Strings

A string is a bunch of individual characters.

#! /bin/bash

rand_str="A random string"

Getting the length of a string:

#! /bin/bash

echo "String Length : ${#rand_str}"

Slicing a string:

#! /bin/bash

echo "${rand_str:2}"

# get string with starting and ending index
echo "${rand_str:2:7}"

# return whats left after A
echo "${rand_str#*A }"

Arrays

Bash arrays can only have one dimension and indexes start at 0.

#! /bin/bash

fav_nums=(3.14 2.718 .57721 4.6692)
echo "Pi : ${fav_nums[0]}"

Add a value to the array:

#! /bin/bash

fav_nums[4]=1.618
echo "GR : ${fav_nums[4]}"

Output all array values:

#! /bin/bash

for i in ${fav_nums[*]}; do

  echo $i;

done

Output all indexes:

#! /bin/bash

for i in ${!fav_nums[@]}; do

  echo $i;

done

Get number of items in an array:

#! /bin/bash

echo "Array Length : ${#fav_nums[@]}"

Get length of array element:

#! /bin/bash

echo "Index 3 length : ${#fav_nums[3]}"

Sort array:

#! /bin/bash

sorted_nums=($(for i in "${fav_nums[@]}"; do

  echo $i;

done | sort))

for i in ${sorted_nums[*]}; do

  echo $i;

done

Delete array element:

#! /bin/bash

unset 'sorted_nums[1]'

Delete Array:

#! /bin/bash

unset sorted_nums

Functions

Define a function:

#! /bin/bash

getDate () {

  date

  return # return returns an exit status number between 0 - 255

}

getDate # call the function

To use parameters in a functions you need to use local:

#! /bin/bash

getSum () {

  local num3=$1
  local num4=$2
  local sum=$((num3+num4))

  echo $sum

}

num1=5
num2=6

echo "the sum is: $(getSum num1 num2)"
1