🚀 The Missing Shell Scripting Crash Course

godcrampy

Sahil Bondre

Posted on April 21, 2020

🚀 The Missing Shell Scripting Crash Course

Bash is a shell and a command language. You can use it like any other language to write scripts. Bash scripts can run on Linux and Mac right off. For Windows, there's a small workout to be done. In this tutorial I'll be going over Shell Syntax and not Shell Commands like ls, grep, cat.

This crash-course will teach you all the necessary stuff you need to get up and running with writing shell scripts.

1. Hello World

All you need in this tutorial is your terminal and a text editor. Let's write a simple hello world in bash. Create a new file called script.sh and write the following code:

#!/bin/bash

echo "Hello World"
Enter fullscreen mode Exit fullscreen mode

Now save this file. To make this executable, run chmod +x ./script.sh in your terminal. Then you can run the above script using ./script.sh in your terminal.

Hello World
Enter fullscreen mode Exit fullscreen mode

Tah Dah! Your first bash script. Let's examine the code closely. The first line #!/bin/bash is called a shebang. It tells your computer which program to give this code to run. In our case, it is /bin/bash.
If you wanted to write javascript instead of bash you could write the following code.

#!/bin/node

console.log("Hello Javascript")'
Enter fullscreen mode Exit fullscreen mode
$ ./script.sh
Hello Javascript
Enter fullscreen mode Exit fullscreen mode

The above code will work only if you have node installed in /bin/ directory. So essentially you can write code in any language. All you need to do is specify which program can handle that code and your system will pass on that file to that program.

Let's hop back to bash now. In the above code, the second line is echo "Hello World". echo is a command which prints stuff to the Standard Output which is the terminal in our case.

2. Variables

Let's modify the above code a little bit.

#!/bin/bash

name="Bash"

echo "Hello, $name"
Enter fullscreen mode Exit fullscreen mode
$ ./script.sh
Hello, Bash
Enter fullscreen mode Exit fullscreen mode

We create a variable called name and store the string "Bash" to it. Then to access it, we need to reference it with $. If you forget the $ sign, bash will treat name as a string literal, and you'll get Hello name as output instead.

Note that there are no spaces around the = while defining a variable. Also, use double quotes while referencing.

3. User Input

Let's continue modifying our script. We'll request the user for their name and then greet them back.

#!/bin/bash

read -p "What is you name: " name

echo "Hello $name"
Enter fullscreen mode Exit fullscreen mode
$ ./script.sh
What is you name: godcrampy
Hello godcrampy
Enter fullscreen mode Exit fullscreen mode

The read command takes in one line of input from the Standard Input and saves it to the variable name. The -p flag allows us to pass a prompt of "What is your name: " before taking in the input.

One neat trick to reference variables in a string is to use curly braces:

#!/bin/bash

read -p "Enter an action: " verb

echo "You are ${verb}ing"
Enter fullscreen mode Exit fullscreen mode
$ ./script.sh
Enter an action: cook
You are cooking
Enter fullscreen mode Exit fullscreen mode

4. Comments

# Comments start with hash
Enter fullscreen mode Exit fullscreen mode

Multiline Comments are a bit of a complicated mess.

5. Arguments

$1, $2 and so on, store the arguments passed into the script. $0 stores the file name.

#!/bin/bash

echo $0
echo $1
echo $2
echo "${@}" # Access all the arguments [More on this later]
Enter fullscreen mode Exit fullscreen mode
$ ./script.sh first second
./script.sh
first
second
first second
Enter fullscreen mode Exit fullscreen mode

6. Expressions

There are 3 common expressions: return values, arithmetic evaluation and test command. All three of these return either a true or false value.

Return Values
This is literally the return value of programs like grep, find.

Arithmetic Evaluation
Bash uses a parenthesis to denote arithmetic expressions.
Example: (( 1 <= 5))

Test Command
The test command often denoted by [ or [[ can carry out more complex operations:

[[ -e "$file" ]] # True if file exists
[[ -d "$file" ]] # True if file exists and is a directory
[[ -f "$file" ]] # True if file exists and is a regular file
[[ -z "$str" ]]  # True if string is of length zero
[[ -n "$str" ]]  # True is string is not of length zero

# Compare Strings
[[ "$str1" == "$str2" ]]
[[ "$str1" != "$str2" ]]

# Integer Comparisions
[[ "$int1" -eq "$int2" ]] # $int1 == $int2
[[ "$int1" -ne "$int2" ]] # $int1 != $int2
[[ "$int1" -gt "$int2" ]] # $int1 > $int2
[[ "$int1" -lt "$int2" ]] # $int1 < $int2
[[ "$int1" -ge "$int2" ]] # $int1 >= $int2
[[ "$int1" -le "$int2" ]] # $int1 <= $int2
Enter fullscreen mode Exit fullscreen mode

Note that [ is actually a command. Try running $ where [.
test, [ and [[ are almost similar. There are a few subtle differences.

And & Or

[[ ... ]] && [[ ... ]] # And
[[ ... ]] || [[ ... ]] # Or
Enter fullscreen mode Exit fullscreen mode

7. Conditionals

Now since we know, expressions let's use them in conditional statements.

# 1. Return values

# If notes.md file doesn't exist, create one and 
# add the text "created by bash"
if find notes.md
then
  echo "notes.md file already exists"
else
  echo "created by bash" | cat >> notes.md
fi
Enter fullscreen mode Exit fullscreen mode
# 2. Arithmetic Evaluations
read -p "Enter your age: " age

if (( "$age" > 18 ))
then
  echo "Adult!"
elif (( "$age" > 12 ))
then
  echo "Teen!"
else
  echo "Kid"
fi
Enter fullscreen mode Exit fullscreen mode
# 3. Test Expressions
# Check if argument was passed
# "$1" corresponds to first argument
if [[ -n "$1" ]]
then
  echo "Your first argument was $1"
else
  echo "No Arguments passed"
fi
Enter fullscreen mode Exit fullscreen mode

The if statement has to end with fi.

If you are keen enough, you might wonder why I am using "$var" and not $var to reference the variables. Here's your answer. (Hint: Both work but double quotes are safer).

8. Looping

# print numbers 1 to 10

# c like for loop
for (( i = 1; i <= 10; ++i ))
do
  echo "$i"
done

# for in
for i in {1..10}
do
  echo "$i"
done

# while
i=1
while [[ "$i" -le 10 ]]
do
  echo "$i"
  ((i++))
done

# until
i=1
until [[ "$i" -eq 11 ]]
do
  echo "unitl $i"
  ((i++))
done
Enter fullscreen mode Exit fullscreen mode

Iterating over arrays
Arrays are declared using parenthesis without commas between elements. More on arrays later on.

arr=(a b c d)

# For in
for i in "${arr[@]}"
do
  echo "$i"
done

# c like for
for (( i = 0; i < "${#arr[@]}"; i++))
do
  echo "${arr[$i]}"
done

# while
i=0
while [[ "$i" -le "${#arr[@]}" ]]
do
  echo "${arr[$i]}"
  (( i++ ))
done
Enter fullscreen mode Exit fullscreen mode

${arr[@]} allows you to iterate over an array while ${#arr[@]} returns the length of the array.

Iterating over arguments
@ holds all the arguments passed in to the script

for i in "$@"
do
  echo "$i"
done
Enter fullscreen mode Exit fullscreen mode

continue and break work the same way as in other programming languages. continue skips the current iteration. break quits the loop.

9. Arrays

Arrays in bash are defined with parenthesis with no commas separating the elements.

arr=(a b c d)
Enter fullscreen mode Exit fullscreen mode

Read

echo "${arr[1]}"     # Single element
echo "${arr[-1]}"    # Last element
echo "${arr[@]:1}"   # Elements from 1
echo "${arr[@]:1:3}" # Elements from 1 to 3
Enter fullscreen mode Exit fullscreen mode

Insert

arr[5]=e                            # direct address and insert/update
arr=(${arr[@]:0:1} new ${arr[@]:1}) # Adding 'new' to array
Enter fullscreen mode Exit fullscreen mode

Delete

arr=(a b c d)
unset arr[1]
echo << "${arr[1]}" # Outputs nothing
Enter fullscreen mode Exit fullscreen mode

Notice how once we delete the element at position 1, the following item does not take up its place. Once removing is done, we need to re-index the array.

arr=(a b c d)
unset arr[1]
arr=("${arr[@]}")
echo << "${arr[1]}" # c
Enter fullscreen mode Exit fullscreen mode

10. Functions

Functions in bash have a kind of similar syntax as in other programming languages. Arguments to a function are accessed identically to the arguments to the script.

greet() {
  echo "Hello, $1"
}

greet Bash # Hello, Bash
Enter fullscreen mode Exit fullscreen mode

The function definition does not specify any information of the arguments passed to it. Notice how while calling a function, parenthesis is not used. Instead, arguments are passed in separated by space.

All the arguments of a function can be accessed using @.

greet() {
  echo "Hello, ${@}"
}

greet every single body # Hello, every single body
Enter fullscreen mode Exit fullscreen mode

And that's it for this crash course. You can now start writing your own shell scripts. There's more to be explored beyond what I have mentioned here.

🌟 I made some Cheat-Sheets
🚀 Find me on Instagram | Github | Twitter | Website
😄 Have a wonderful day!

💖 💪 🙅 🚩
godcrampy
Sahil Bondre

Posted on April 21, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related