- 9 mins

# How to write bash scripts

## Introduction

This is a quick crash course on how to do the basics of bash scripting.

First we need some definitions:

Terminal: What is used to take in input and print output. However, the terminal doesn’t know what to do with this.

Shell: The shell interprets what the user types in and executes those commands. We can also use the python interpretor shell to run commands.

Bash: A type of shell program. This is the default on lots of systems. Bash came from sh (shell command language) but now has more features.

Bash is quite useful for small task automation. Not really a good idea for large scale software development. If you’re writing more than 50 lines of code, it is recommended to use other languages.

## Getting Into It.

echo "Hello"


Returns standard out. If we want to store it, we can redirect it into another file.

echo "Hello" > new.txt  # use >> to append to a file.


We can count the number of lines in a file by the wc command.

wc -l < file.txt


The flow of data is reversed here since the file on the right is going in as the input to the command on the left. The -l flag will count the number of lines in the code. A more conventional and intuitive way of doing this is going:

cat file.txt | wc -l


This pipes the output of the cat command as the input for the wc command.

We can execute multiple commands with the && command.

cat file.txt | wc -l && echo "It worked!"


The latter half of the code after the && will only execute if the first half executes correctly. We can use conditional execution using ||.

## Variables and Quoting

Whenever we have a $, that denotes a variable in bash scripting. When denoting environment variables, or variables outside of the program, we denote them with capital letters such as$HOME.

echo $HOME  To initialise a variable, we can go: myvar="I like potatos"  DO NOT HAVE SPACES WHEN DOING THIS. SHELL WILL THINK IT’S A BUNCH OF COMMANDS. We can then call that variable by going: echo$myvar


To concatenate variables, we can go:

number=5
echo "This is my ${number}th pair of headphones.  We can also do command substitution whereby we include the output of the command in what we are working with. This can be substituted in with the  symbols. echo "There are cat file.txt | wc -l number of files in the file"  To know which bash we are using, we can go: which bash  Bash scripts should start with: #!bin/src #!bin/bash  We can use either src or bash (for my purposes, I’ll use bash). The # indicates a comment and the bin/bash part will tell the path to the bash binary executable. This is for the kernal. This is known as shebang. Naming things with .sh at the end doesn’t actually matter for Linux operating systems but is good practice and helps other people figure out what is going on. Exit code 0 means there is no error with the code being executed. We can include exit$?


At the end, similar to return 0 in C.

We need to change the file mode to run shell scripts to be executable as well.

chmod +x myscript.sh


We can run shell scripts in 3 different manners:

./myscript.sh
bash myscript.sh
source myscript.sh


We can also pass in arguments to our file. Note that the first argument is the name of the script.

ourfilename=$0 echo$ourfilename # name of file


For numerous arguments, we can go:

arg1=$1 arg2=$
echo "Our arguments are ${arg1} and${arg2}:


## Control Flows

X="Dog"
if [ "$X" = "Dog" ]; then echo "Hello" fi echo "Bye"  We can have multiple conditions for the logic flow: if [ "$X" = "Dog" ]; then
echo "Hi"
elif [ "$X" = "Cat"]; then echo "I hate cats" else echo "Nevermind!" fi  We use the symbol -lt as the less than sign. Hence, we can test whether has there been a certain number of variables passed into the code. The list for binary opeartors are: -eq (Check if they are equal) -ne (Check if they are not equal) -gt (Check if the LHS is greater than the RHS) -ge (Check if the LHS is greater than or equal to RHS) -lt (Check if the LHS is less than the RHS) -le (Check if the LHS is less than or equal to the RHS) arguments_needed=5 if [$# -lt arguments_needed ]; then
echo "Not enough arguments."
fi


The $# counts the number of arguments being passed into the script. We can also use || again. echo "Hello" || echo "Bye"  Here, we only execute the LHS since that is true and it won’t bothered running the RHS. If the LHS was not true, then the RHS will execute instead. if [ "$str1" != "$str2" ]; then echo "${str1} is the same as ${str2}" fi  To check if something is not null, we can use -n. To check if length is 0, then we can use -z. if [ -n "$word" ]; then
echo "This word is not null!"
if [ -z "word" ]; then
echo "The length of the string is 0!"
fi


## Functions

If we want to use for loops, we go:

for arg in "$@"; do echo "$arg"
done


$@ symbol is an array containing all the arguments passed into the file. Hence, arg will iterate through the array. We define functions by going: function mycode (){ echo "Hi there$1" # The $1 refers to the second arguments passed into this function specifically. } function runcode (){ mycode chris # in bash, you don't have () to pass in arguments for functions }  The runcode function will call the mycode function and the argument passed in is chris. ## Input We can read input in with the read command. read varname echo "Hey there${varname}"


The tr utility copies the given input to produce output with substitution or deletion of selected characters. tr stands for translated/transliterate. It takes 2 sets of characters and replaces the first ones with the latter ones.

echo 'linux' | tr "[:lower:]" "[:upper:]"
echo 'linux' | tr "a-z" "A-Z"


These two lines are equivalent.

echo 'linux' | tr l q  # this will print out qinux


We can also translate characters around.

echo "linux" | tr ['a-z'] ['c-z']


This will shift everything two characters down. To make sure it works for when we go past the letter z, we go:

echo "linux" | tr ['a-z'] ['n-za-m'] # This will shift it by 13 spots


To make it case insensitive:

#!bin/src
echo "${varname}" | tr [A-Za-z] [N-ZA-Mn-za-m]  We can manipulate for loops like we would in Python for file_var in ls; do echo file:$file_var
done


This prints out all the files in the current directory.

To keep on processing things as long user gives input, we go:

while [ true ]; do
if [-z "$varname" ]; then break fi # Command to do stuff done  This will continuously run stuff until user stops giving in input. We can also traverse directories using cd etc in Bash. This will take in a folder as first argument and the file extension to search for. #!bin/src cd${1}
ls | grep -i ${2}$