Bash

Executing Scripts

By convention, bash scripts end with the .sh file extension. You can make a script executable using chmod e.g. chmod u+x my_script.sh. You can then run the script with ./my_script.sh, sh my_script.sh, bash my_script.sh

Add a shebang to let your shell know what to execute the script with. For bash, this is the path to where bash is e.g. #!/bin/bash

Comments

Comments can be written using the # character

Variables

Bash has no data types. A variable can store numeric values, characters, or strings. You use the $ operator to access a variable’s value

Assigning and accessing variables
my_var=hello
echo $my_var

# also valid
echo ${my_var}

Note

Variable names are case sensitive

  • You are also able to have global and local variables:

Example with global and local vars
VAR="global variable"

function bash {
    # Define bash local variable
    # This variable is local to bash function only
    local VAR="local variable"
    echo $VAR
}
  • Arrays:
    • 4 element array: ARRAY=(MY NAME IS 4)

    • Get number of elements in an array: ELEMENTS=${#ARRAY[@]}

    • Loop through array:

Example looping through array
for (( i=0;i<$ELEMENTS;i++)); do
    echo ${ARRAY[${i}]}
done

Input and Output

  • User input - use the read command: read var_to_hold_input

  • Read lines of a file:

while read line
do
    echo $line
done < input.txt
  • Command line args. You can access arguments passed through the command line with $1, $2 ....
    • Can access all arguments through a special character: $@

    • Could place in an array like so: args=("$@"), and access them with args[0], args[1]...

  • Printing to the terminal: echo "Hello World"

  • Writing to a file: echo "Some text." > output.txt. Can also redirect commands: ls > output.txt

Note

The > operator overwrites a file if it already has content in it

  • Appending to a file: echo "More text." >> output.txt

Conditional Statements

  • If and else statements take the following form:

if else example
if [ condition ]; then
    statement
elif [ condition ]; then
    statement
else
    statement
fi
  • You can use logical operators in the condition check, e.g. -a (AND), -o (OR), -gt (>), -lt (<), -le (<=) etc.

Note

There is a slight difference between using double [[]] and single [], but mostly can be used in a similar way

Looping and Branching

  • While loop:

Example while loop
i=1
while [[ $i -le 10 ]] ; do
    echo "$i"
    (( i += 1 ))
done
  • For loop:

Example of a for loop
for i in {1..5}
do
    echo $i
done
  • Until loop: works like a while loop almost

Until loop example
#!/bin/bash
file="./file"
if [ -e $file ]; then
    echo "File exists"
else
    echo "File does not exist"
fi
  • Case statements:

Example case statement
case expression in
    pattern1)
        # code to execute if expression matches pattern1
        ;;
    pattern2)
        # code to execute if expression matches pattern2
        ;;
    pattern3)
        # code to execute if expression matches pattern3
        ;;
    *)
        # code to execute if none of the above patterns match expression
        ;;
esac

Scheduling with cron

Cron is a utility that allows you to schedule jobs. on Unix-like systems

Syntax for cron and some examples
# syntax
# represents mins, hours, days, months, weekday
* * * * * sh /path/to/script.sh

# midnight every day
0 0 * * * sh /path/to/script.sh

# every 5 minutes
*/5 * * * * sh /path/to/script.sh

# 6am mon-fri
0 6 * * 1-5 sh /path/to/script.sh

# first 7 days of every month
0 0 1-7 * * sh /path/to/script.sh

Note

You can manage and edit cron jobs using crontab. e.g. crontab -l lists all cron jobs for a user

  • cron logs can be found at /var/log/syslog

Debugging

  • Use set -x at the start of your bash script
    • This will print each command it executes to the terminal

    • You can also just pass in the flag when calling the script: bash -x my_script.sh

  • Checking exit code: $? will give the exit code of the previous command

  • Use the -e flag to make your script exit on an error, and not keep running
    • Can also do set -e at the start

Executing Shell Commands in bash

  • You can create a new subshell with $( )

  • It is then possible to use this output in other commands:

Example using subshell
echo "My current git branch is $(git branch --show-current)"

Bash Trap

Bash can catch signals that you send to it, e.g. ctrl+c

Example catching a signal interrupt
trap bashtrap INT

# bash trap function is executed when CTRL-C is pressed:
# bash prints message => Executing bash trap subrutine !
bashtrap()
{
    echo "CTRL+C Detected !...executing bash trap !"
}

# rest of script

Comparison Operators

  • Arithmetic:
    • -lt (<)

    • -gt (>)

    • -le (<=)

    • -ge (>=)

    • -eq (==)

    • -ne (!=)

  • String:
    • =: equal

    • !=: not equal

    • <: less than

    • >: greater than

    • -n s1: string s1 is not empty

    • -z s1: string s1 is empty

File Testing

It is possible to test characteristics of files/directories in bash:

  • -d dir_name: Check if dir exists

  • -e filename: Check if file exists

  • -L filename: Symbolic link

  • -r file: File is readable

  • -s file: File is non-zero size

  • -w file: File is writable

  • -x file: File is executable

Example with file testing
#!/bin/bash
file="./file"
if [ -e $file ]; then
    echo "File exists"
else
    echo "File does not exist"
fi

Functions

Example function
function my_func {
    echo 5
}

function my_arg_func {
    echo $1
}

echo "My special number is ${my_func}"
echo "My special number is ${my_arg_func 3}"

Select

Use this to promt the user to select from a number of options

Example using user selection
PS3='Choose an option: '
select word in "Yes" "No"
do
    echo "You chose ${word}"
    break
done

Single and Double Quotes

Single quotes in bash will suppress special meanings of meta characters.

Double quotes suppresses the meanings, except from $ \ In this case you can use escape characters like: \a -> alert (bell)

Let keyword

let is used when evaluating arithmetic expressions on shell variables

let my_var++

Redirecting STD streans

  • STDOUT to STDERR:

    echo "Redirect" 1>&2

  • STDERR to STDOUT

    cat $1 2>&1

exec command

Bash includes a built-in command called exec. Calling this replaces the process of the current shell with a process of the command specified after the exec command.

Because the command is replacing the shell, it will cause a bash script to end after executing.

Example of return
exec echo "Hello"
exec echo "World"

The above example only prints β€œHello”

It can also be used for redirecting std streams to log files:

Example routing stdout to log file
exec 1>log.txt

echo "Hello"
echo "World"

β€œHello World” is written to the log.txt file.

Note

STDIN is 0, STDOUT is 1, and STDERR is 2

Bash eval statement

The eval statement allows you to run a command based on a variable.

Example using eval statement
MY_COMMAND="git br -a"

eval $MY_COMMAND > my_file.txt

RETURN_CODE=$?

Environment File

You can make an environment file, containing for example environment varibales and include this in your bash script.

Example environment file
# my_values.env

COLOR="black"
Example using environment file
#!/bin/bash

source ./my_values.env
echo $COLOR

bashrc file

Your ~/.bashrc file is run when you load a new bash terminal. Here, you can alter the default file to provide custom functionality.

Git Branch Label

One customization you can do for example is to include a label on your bash promt telling you which git branch you are currently on, if you are in a git directory. You can do this by altering the PS1 variable:

Adding git branch label to bash prompt
# Full prompt
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\[\033[01;31m\]$(git branch --show-current > /dev/null 2>&1 && echo " [$(git branch --show-current)]")\[\033[00m\] \$ '

# Newly added section
# $(git branch --show-current > /dev/null 2>&1 && echo " [$(git branch --show-current)]")\[\033[00m\] \$