Table of Contents:
What is Bash?
Bash is a command-line shell and scripting language that is widely used in Unix-like operating systems such as Linux and macOS. Bash stands for “Bourne Again SHell,” a play on the earlier “Bourne Shell” it was designed to replace. Bash was created by Brian Fox in 1989 while working at the Free Software Foundation. He developed it as a free software replacement for the Bourne shell (sh), adding more features like command history, better scripting capabilities, and improved user interaction. Later, Chet Ramey became the primary maintainer and has overseen Bash’s development for decades, ensuring it remains stable and widely used across Linux and Unix-like systems.
Note:
In some examples, you’ll see a
$at the beginning of a command. This symbol indicates that the command should be run in a terminal. You don’t type the$itself, only the text that follows it.
To use bash, you need to confirm it’s installed on your system. Run:
$ bash --version
If you see output like GNU bash, version X.X.X(X)-release, bash is installed. If instead you get an error, bash isn’t available on your device, and you won’t be able to use it there.
Note:
In Bash, the
#symbol is used to mark a comment. Everything written after#on the same line is ignored by the shell. Comments are helpful notes added to code to explain what it does, making programs easier to read and maintain.# This is a comment!
Bash Commands
In Bash, commands are instructions you type into the shell to make the computer do something. They can be built-in functions of the shell, external programs, or scripts you write yourself.
Bash commands usually follow this syntax:
command options/flags arguments
For example:
$ ls -l /etc
ls is the command, it stands for “list”. It lists the files and folders in a directory.
-l is an option/flag. It displays detailed information of those files and folders. Some commands don’t require options (or flags), so you can pass the argument directly without options.
/etc is the argument, it is a path to a directory. It tells ls to “list” all the files and folders in the /etc directory.
Note:
A path is like an address that tells the shell where a file or directory is located. There are two main types of paths:
Absolute Paths:
Absolute Paths always start from the root directory
/. They point to the same location regardless of your current working directory. Here is an example of an absolute path:/usr/bin/env. This always refers to theenvexecutable.Relative Paths:
Relative Paths start from your current working directory. For example:
Downloads/file.txt. It refers tofile.txtinsideDownloads, but only ifDownloadsexists in your current directory. Special symbols can change the starting point:. # Refers to the current directory .. # Refers to the parent directory ~ # Refers to the home directory of the current user # Usage: ./file.txt # Points to file.txt in the current directory ../file2.txt # Points to file2.txt in the parent directory ../../test/ # Points to the test directory two levels up ~/Downloads # Points to the Downloads folder in the user's home directory
Here are some common, built-in Bash commands:
cat [options/flags (optional)] [arguments]catstands for “Concatenate.” It displays the contents of files or merges multiple files together.
cd [options/flags (optional)] [path]cdstands for “Change Directory.” It moves you into the specified directory (default is current directory).
echo [options/flags (optional)] [text]echois used to display messages or variable values.
exit [status code (optional)]exitends the current shell session or script. The status code0means success;1–255indicate errors.
help [options/flags (optional)] [command (optional)]helpshows information about built-in Bash commands, including available options and arguments.
logout [status code (optional)]logoutlogs you out of your current user session (with a status code).
ls [options/flags (optional)] [path]lsstands for “List.” It displays files and directories in the given path (default is current directory).
There are many more commands available. Use help or check your operating system’s documentation to explore them further.
Scripting in Bash
A Bash script is simply a text file containing a series of Bash commands that the shell can execute in order, rather than you typing them one by one in the terminal.
Bash scripts are very easy to write. To create one, start by making a file with the .sh extension. Directly at the top of the file, it’s best practice to include a shebang:
#!/usr/bin/env bash
The shebang (#!) at the start of a script tells the system which interpreter to use. An interpreter is a foundational programming tool that executes written code. In this case, #!/usr/bin/env bash locates the bash interpreter via the env command and runs the script with it.
Once you’ve finished writing a Bash script, the next step is to run it on your computer. Before you can execute the script, you need to give it permission to be executable:
$ chmod +x script.sh
Replace script.sh with the name of your script. Once it’s executable, you can run it in different ways:
$ bash script.sh # Executes the script using bash
$ sh script.sh # Executes the script using sh (also invokes bash in most systems)
$ ./script.sh # Runs the script directly, but requires a proper shebang at the top
Variables
A variable is like a labeled container that holds information. Imagine you have a box with a sticky note on it that says “greeting.” Inside the box, you can put anything: a word, a number, or even the result of a command. Later, you can open the box and use whatever is inside without rewriting it.
Instead of repeating the same value over and over, you give it a “nickname” (the variable name) and reuse it.
The basic format of a variable in Bash is:
variable_name=value
Important:
There should be no spaces around the
=sign.
Here is an example of storing “Hello!” into the variable greeting:
greeting="Hello!"
Note:
In Bash, variables are not strongly typed, meaning Bash doesn’t enforce strict data types like integers or floats. Instead, they are treated as strings by default, but you can use them in different contexts (like arithmetic or environment variables).
To use the value inside a variable, put a $ before its name:
echo $greeting
If you execute the script, it should return Hello! in the console. Now replace “Hello!” in the greeting variable to 5:
greeting=5
If you execute this, it will output 5.
Bash runs scripts line by line from top to bottom. That means the order matters. So if you write something like:
greeting="Hello!"
echo $greeting
greeting=5
It will output Hello! because echo happened before greeting was changed.
You can do arithmetic on variables using operators. Operators are symbols or keywords that let you perform actions on values or variables. Here is a list of all the operators:
|
Operators |
Math |
|
* |
Multiplication |
|
/ |
Division |
|
+ |
Addition |
|
– |
Subtraction |
|
** |
Power To |
|
& |
Bitwise AND |
|
| |
Bitwise OR |
|
^ |
Bitwise XOR |
|
~ |
Bitwise NOT |
|
<< |
Left Shift |
|
>> |
Right Shift |
To do math, wrap your expression in double parentheses (( )). Inside (( )), you don’t need $ before variable names. Here is an example:
x=10
y=2
(( z = 5 * 5 )) # Creates the variable z and sets it to 5 times 5 (5 * 5 = 25)
(( z = x / y )) # Reassigns z (since it was created before) with x (10) divided by y (2) (10 / 2 = 5)
echo $z # Outputs 5
If you execute this script it will output the number 5.
You can store the result of a command inside a variable using $( ). This is the format:
variable_name=$(command options/flags arguments)
Here is an example:
cores=$(nproc)
echo "You have $cores cores available."
nproc is a command that returns the number of logical CPUs available to the current process. The script runs nproc, stores the returned number in the variable cores, and then echoes something like: “You have 8 cores available.” (The actual number depends on your computer).
Bash also has environment variables, special variables that affect how programs run. Here is a list of common environment variables:
|
Environment Variables |
Stores |
|
$HOME |
The absolute path to your home directory. |
|
$PATH |
The list of directories Bash searches for commands. |
Conditionals
Conditional structures in scripting are rules that let your code make decisions. They check whether something is true or false and then choose which block of code to run. In Bash, conditional structures use numeric comparison operators (for numbers), string comparison operators (for strings), file test operators (for files and directories), and logical operators. You can find the whole list of operators here.
If-Else statements in Bash are conditional structures. Here is the syntax:
if [[ operand operator operand ]]; then
...
elif [[ ... ]]; then
...
else
...
fi
An operand can be a variable, a number, or any value to be tested. An operator is the comparison or test itself (e.g., -eq, -gt, ==). The condition compares the two operands using the operator and evaluates whether it is true.
If the initial if condition is true, its block executes. If it is false, Bash moves on to the next condition specified by elif. The keyword elif stands for “else if” and is only checked when the previous if (or another elif) fails. You can include multiple elif branches in a single if-else chain.
If none of the if or elif conditions are true, the else block executes. This acts as the “catch-all” case when every other condition fails.
Here is an example of an If-Else statement:
x=5
y=4
if [[ $x == $y ]]; then
exit 0 // This won't execute because the if statement above is false.
elif (( x + y = x + y )); then // Using (( )) to do arithmetic on x and y.
exit 0 // Because the elif is true, this will be executed.
else
exit 1 // This will never be reached because the elif above is true.
fi
The elif was true so the exit command in there will execute.
In Bash, case statements are conditional structures. They match a variable or expression against multiple patterns and execute code depending on which pattern matches. They look and act like switch statements in other programming languages. This is the syntax:
case expression in
pattern1)
...
;;
pattern2)
...
;;
pattern3|pattern4)
...
;;
*)
...
;;
esac
The expression could be a variable or just an expression with operators. The patternN are compared to the expression to see if they are equal and execute the code inside. The ;; are breaks so Bash can exit the case after the code in the pattern finished. You can use a | in a case block. The | is used to separate multiple patterns that should trigger the same block of code. If no pattern matched, then the code under the * is executed. The * is the default and will only always execute if no pattern was found. The esac just ends the case statement.
Here is an example of a case statement:
animals="cows"
case $animals in
"sheep")
echo "There are sheep!" // This won't execute because $animals isn't sheep
;;
"cows")
echo "There are cows!" // This will execute because the pattern is true
;;
*)
echo "There are animals!"
;;
esac
