Variables

Variables are storage locations with a name assosiated to it which content can be manipulated (assign and read). To define a variable, use variable="value" syntax.
Do not add spaces before or after the equal sign!

#!/bin/bash
var1="hi" #will work
var1 = "hi" #will not work

Just like in all other programming languages, variables are case sensitive. The name of the variable can be letters, digits and underscores. (a-z,A-Z,0-9,_).
There are some restrictions: variable names can not start with a digits and don't use special characters on the names because they might have a specific meaning in the Bash. You can use CAPITAL lettes, lower letters or CamelCase when you define a new variables, what suits the best for you.

Existing variable values can be overwritten using the same syntax: old_variable=new_value. If you want to prevent this, you can use Bash's builtin command readonly. Syntax: readonly VARIABLE.

#!/bin/bash
var1="hi"
echo $var1
var1="hello"
echo $var1
readonly var1
var1="hey"

#output:
#hi
#hello
#var1: This variable is read only.

You can also assign the output (stdout) of a specific command to a variable. This is also known as a command substitution.
Enclose the command in parentheses with a dollar sign prefix $.

#!/bin/bash
var1=$(whoami)
var2=$(pwd)
echo $var1
echo $var2

#output:
#user
#/home/user

Accessing variable values

To access the stored value, add a dollar sign $ as a variable prefix.
If the referred variable doesn't exist or doesn't store any values, script won't fail! Bash returns an empty string.

#!/bin/bash
var1="hi"
echo $var1
echo $var2

#output:
#hi
#(empty line)

NOTE:
The earlier way exposes variable value to the word splitting by IFS (Internal File Separator). As the name states, it is a shell variable that is used to describe what is used to split words. By default it uses a spaces, tabs and newlines as a delimiter.

Quoting a variable reference ("$var") prevents word splitting and glob expansion.
You will see the difference better when iterating a string.

#!/bin/bash
var1="hi all students"

for x in $var1:
do
  echo $x
done
#output:
#hi
#all
#students

#When quoting the variable reference:

for x in "$var1":
do
  echo "$x"
done
#output:
#hi all students

If you need to immediately precede or follow the variable with additional data you must encapsulate variable name with a curly braces {}. If you dont do this, shell will treat the additional text as a part of the variable name. Since variable with that name likely unexist, nothing is put in its place.

#!/bin/bash
var1="class"
echo ${var1} #works the same way as normal syntax
echo "$var is full" #works fine
echo "$var1room" #FAILS because it searches a variable called var1room: output: empty
echo "${var1}room" #WORKS: output: classroom

#output:
#class
#class is full
#
#classroom

Quotes

The shell doesn't care about type of the variables, but Bash uses spaces to determine items. When you want to store complex values to variables, you have to use single or double quotes '' or "". Quotes indicate bash that the value should be considered as a single item.

#!/bin/bash
var1=hi students
echo ${var1}

#output:
#students: command not found
  • Single quotes will treat every character literally
  • Double quotes will allow to do substitution
#!/bin/bash
var1="hi"
say1="say $var1"
say2='say $var1'
echo $say1
echo $say2

#output:
#say hi
#say $var1

Special variables

There are multiple variables that the system sets automatically:

  • $0 = The filename of the current script
  • $1-9 = The first 9 command line arguments passed to the script
  • $# = How many command line arguments were given
  • $@ or "$@" = All the command line arguments given
  • $$ = The process ID of the script
  • $? = exit status of the last executed command of the script

NOTE Unless $@ syntax is not wrapped in double quotes (" "), single strings are exposed to a word splitting when doing looping ("i'm a dog" is regonized as a 3 items, not one string)!


Comments

In Bash, the comments are marked using a hash # (just like in Python). The only exception is on the first line, shebang. When the hash # is encountered, the interpreter ignores everything that follows it on the same line (on the right side). Even if the line starts with the hash # the hole line is ignored.

#!/bin/bash
var1="im a variable" #just showing how comments work
#comment that means nothing...

#output:
#im a variable

Bash also supports so called multiline comments where the defined block of code is commented.
Start the comment block on the empty line with a two "smaller than" signs << followed by the comment name: <<my_comment. End the comment block on the empty line using the comment name: my comment. Note that if the block name has spaces, you must encapsulate the name in quotes ""!

#!/bin/bash
var1="im a variable"

<<unnecessary
var2="im a variable called 2"
var3="im a variable called 3"
var4="im a variable called 4"
unnecessary

#output:
#im a variable

Commandline arguments

When you run a program from the command line, command usually need some kind of command line arguments control it's behavior.

Usually these arguments are supplied after the main command, for example: ls lists the content of the current folder and ls -la list also a hidden files and extra information about the files. Same principle applies to Bash scripts. Additional arguments can be supplied when starting the script.

Possible command line argument names are reserved and named as $1 -->. These are also known as positional parameters because you dont have to define them beforehand. $0 is the name of the current script. $1 present the first command line argument after the script name, $2 the second one and so on.
The get all the given arguments (except the script name), use "$@".
These variables are automatically set when running the script so no need to define these, just refer to them.

#!/bin/bash
echo $1 $2

execution:
$ ./example.sh hi students

#output:
#hi student

User Input

To make a script as general usage as possible it might be good practice to ask values from stdin/user and prevent the script modifications.
In order to get the input from stdin, use the builtin command read command: read <variable name>.

#!/bin/bash

echo "Hi! Whats your name?" # print the welcome text

read name # gets the input to a variable called varname

echo "Nice to meet you $name" # print the string + variable value

If we take this a little further, read command have multiple optional arguments. The most common ones are:

  • -p = adds prompt message
  • -s = hides the input from terminal (silent)

Syntax: read -p "PROMPT" VARIABLE

#!/bin/bash

read -p "username:" name
read -sp "password:" pass
echo "welcome back ${name}!"

You can also supply several variable names to read command. Read will take user input and split it on whitespace. The first item will then be assigned to the first variable name, the second item to the second variable name and so on.
If user gives more items than there is variables, last ones are combined to the last variable. Other way around, if user gives less items than variables, the remaining variables will be blank.

#!/bin/bash

read var1 var2 var3
echo "$var1 $var2 $var3"

Little about Echo command

Like you have already seen in the examples above, echo is a Bash builtin command, used to print string to the standart output (terminal).
Echo has a few options available: echo.

The most common one option -e, that enables interpretation of backslash escapes. This means you can use familiar syntaxes to format your string! Mostly used is \n to force a linebreak between a string.

#!/bin/bash
echo -e "example\nstring"

#output:
example
string