The first encounter I had with the command line was at a relative's house many years ago. I was captivated by the sight of my relative effortlessly typing what seemed like cryptic commands onto a black screen. To me, that was the epitome of what a programmer looked like. Eager to explore this mysterious world, I rushed home and opened up the command prompt. With a mix of excitement and curiosity, I began typing commands that I had memorized, such as cd
and mkdir
, even though I didn't understand their functions at the time. However, these once-unfamiliar commands began to reveal their purpose and significance as I learned more about programming. Now, equipped with a better understanding, I'm thrilled to introduce you to the fascinating world of bash scripting. In this brief tutorial, I'll assume that you're already familiar with basic Linux commands like echo
, ls
, cd
, mkdir
, and nano
.
Bash scripting allows you to unlock the true potential of the command line.
Let's break things down. What does bash mean?
Bash stands for Bourne-Again Shell. It is a command line interpreter It executes commands read from a standard input or a file. It's the default shell for most Unix-like operating systems, including Linux and macOS.
Now what does scripting mean?
Scripting is the process of writing and executing scripts using the Bash shell. A script is a series of commands and instructions that are written in a scripting language (in this case, Bash) and executed sequentially.
Time to create your first script
Open any text editor. Create a file and name it anything with a
.sh
extension. For example,myscript.sh
.
I am using Nano text editor. To open a new file on nano, typenano <name of your file>
in your command prompt on your Linux or Mac, or WSL if you are using a Windows computer.The hashbang: The hashbang or the shebang is the first line of a bash script. It consists of a hash character (
#
) followed by an exclamation mark (!
). The shebang is then followed by the path to the interpreter executable. This shebang line tells the system to use the Bash interpreter located at/bin/bash
to execute the script.
In a Bash script, it looks like this:
#!/bin/bash
Note also that a comment in Bash begins with the (#
) symbol
- Basic "Hello World!": To display anything on the command line, we use the echo command.
#!/bin/bash
echo "Hello World!"
- Make the script executable: Before we can run this script, we have to grant it execute permission using the
chmod
command. Navigate to the directory where the script is stored and run the following:sudo chmod +x myscript.sh
Runls -l
and we'll see that the color of the file name is now green. Also,rwxr
indicates that the user has read, write and execute rights.
- Run the Script: Navigate to the directory containing your script and execute it using its filename. In your case:
./myscript.sh
This is just a glimpse into the world of bash scripting. As you progress, you will explore variables, arithmetic operations, conditional statements, loops, and functions.
Variables
Just like in other programming languages, a variable is a container that stores some data. Variable names in Bash consist of alphanumeric characters and underscores (a-z, A-Z, 0-9, _). They cannot start with a digit. Conventionally, variable names are written in uppercase, but this is not mandatory.
To assign a value to a variable, we use the =
operator with no spaces around it.
#!/bin/bash
myvar=23
name="Ayo"
So, let's store "Hello World!" in a variable called myvar
and display it on the screen.
#!/bin/bash
myvar="Hello World!"
echo $myvar
What's with the dollar($
) sign?
To access the value stored in a variable, we prefix the variable name with a dollar sign. If you don't do that in the example above, "myvar" will be displayed instead of "Hello World!".
Feel free to try different examples in your text editor.
Arithmetic Operations
Arithmetic operations are possible in almost all programming languages and Bash is no different. The table below shows some arithmetic operations and their symbols in Bash.
Operation | Symbol |
---|---|
Addition | + |
Subtraction | - |
Multiplication | * |
Division | / |
Modulo (Remainder) | % |
Exponentiation | ** |
Increment | ++ |
Decrement | -- |
To write a simple math expression, we use the expr
command. For example, 10 + 3 will be written as:
expr 10 + 3
To store the result of an expression in a variable, we can use the double parenthesis: $((...))
.
#!/bin/bash
result=$((10+3))
echo result
The result of the expression 10+3
is stored in result
and the result of 13
is displayed.
Arithmetic operations with variables are also possible. Storing your values in variables before performing computation helps improve your code's readability and flexibility. Try the following example:
#!/bin/bash
num1=100
num2=4
result=$(($num1 % $num2))
# or result=$(expr $num1 % $num2)
echo $result
In the example above, we stored 100 and 4 in num1
and num2
respectively. We then performed the modulo operation which returns the remainder when num1
is divided by num2
: 100 % 4 which will give 0.
So now try this example: 100 divided by 3. Your answer should be 33.333..
#!/bin/bash
num1=100
num2=3
result=$(($num1 / $num2))
echo $result
Did you notice that the fraction part of the result was left out? This is because Bash primarily deals with integers. Bash stores numbers as integers and performs calculations with limited precision.
One solution to this is to use the bc
command. Here's the same example you tried but using the bc
command. You might need to install it if you get an error that bc
command is not found. Install it using this command: sudo apt-get install bc
#!/bin/bash
num1=100
num2=3
result=$(echo "scale:3; $num1 / $num2" | bc)
echo $result
# 33.333 will be displayed
The scale
keyword tells the computer how many numbers you want after the decimal.
Bash Conditionals
Bash conditionals are fundamental constructs used for decision-making within Bash scripts. They allow you to execute different sets of commands based on whether certain conditions are true or false. The primary conditional statements in Bash are the if
, elif
(short for "else if"), else
, and fi
(which signifies the end of an if block) statements.
Before we see how these statements are used, take a look at the table below showing some important numeric comparison operators in Bash scripting. This will be useful later.
Name | Operator |
---|---|
Greater Than | -gt |
Greater Than or Equal To | -ge |
Less Than | -lt |
Less Than or Equal To | -le |
Equal To | -eq |
Not Equal To | -ne |
Now open your text editor and write a script to read a number from a user and check if the number is even or odd.
Haha! We haven't learned how to read user input yet. In bash, we use the read
keyword. To display a prompt, we use the read
keyword with a -p
flag. Here's how it works:
#!/bin/bash
# Read a number from the user and display it:
read num
echo $num
# Prompt the user to enter a number and display it:
read -p "Enter a number: " num
echo $num
In both cases, the number is stored in the num
variable
So, going back to your task, we read the number from the user and check if it's even or odd. Then, we print the corresponding message to the user:
#!/bin/bash
read -p "Enter first number: " num
if [ $(($num % 2)) -eq 0 ]; then
echo "Even Number"
else
echo "Odd Number"
fi
Do you understand the code? If you don't, not to worry. Here is a detailed explanation:
read -p "Enter first number: " num
: This prompts the user to enter a number and stores the input in the variable num
.
if [ $(($num % 2)) -eq 0 ]; then
: checks if the remainder of dividing the number by 2 is equal to 0, indicating that the number is even.
echo "Even Number"
: prints "Even Number" if the condition is true.
else
: executes if the condition in the if
statement is false.
echo "Odd Number"
: Prints "Odd Number" if the number is not even.
Loops
Just like other languages, loops allow you to execute a block of code multiple times.
Bash provides three primary loop statements; for
, while
and until
. You'll explore the for
and while loops
.
The for
loop:
The basic structure of a for loop is:
for item in ${list}; do
# Commands to be executed for each item
done
Write a for loop to display all the numbers from 1 to 5.
#!/bin/bash
for i in 1 2 3 4 5; do
echo $i
done
Another way to do it is by using the following format known as brace expansion:
for i in {start..end..step}; do
or just for i in {start..end}; do
if we want to display all the numbers from the start number to the end without any step.
#!/bin/bash
for i in {1..5}; do
echo $i
done
In either case, your output should be:
To make your code more efficient, use an array to store the numbers and loop through the array.
#!/bin/bash
numbers=(1 2 3 4 5)
for i in ${numbers[@]}; do
echo $i
done
Okay, what's the [@]
used for?
numbers[@]
is used to expand all the elements of the array and the for loop iterates through every element.
Write a Bash script to print out the ages of a person from 1 to 15, incrementing by 2 years for each age.
You can use the brace expansion method I explained previously:
for i in {1..15..2}; do
echo "I am $i years old"
done
Another way to do this is by using the double parentheses.
for ((initialization, condition, increment)); do
for ((i=1; i<=15; i+=2)); do
echo "I am $i years old"
done
for ((i=1; i<=15; i+=2))
has the following features:
- Initialization:
i=1
sets the initial value of the counter variable i to 1. - Condition:
i<=15
checks if i is less than or equal to 15. The loop continues as long as this condition is true. - Increment:
i+=2
increments the value of i by 2 in each iteration.
The while
loop
While we've conquered iterating through predefined lists using the for
loop 😂, Bash scripting offers another powerful tool for repetitive tasks: the while
loop. Unlike the for
loop, which thrives on a set list of elements, the while
loop keeps executing a block of code as long as a specific condition remains true.
The format for a while loop is shown below:
while condition; do
# Commands to be executed while the condition is true
done
Write a while loop to count down from 10 to 5.
- First define a
counter
(where you want to begin counting from) - We want to decrement this
counter
by one during every iteration. So tell the computer that as long ascounter
is greater than or equal to 5, display its value and then decrement by one.
counter=10
while [ $counter -ge 5 ]; do
echo "Countdown: $counter"
((counter--))
done
If you got it right, this should be your output:
Do you have what it takes for the next task?
Write a script to retrieve input from a user until the user enters the string: exit
.
Here's what to do.
- Create an empty variable that will store the user input.
- Write a while loop with a condition that the string value in the variable is not equal to "exit".
-
do
: read the input from the user. -
done
user_input=""
while [ "$user_input" != "exit" ]; do
read -p "Enter 'exit' to quit: " user_input
done
echo "Exit Successful"
So this is what the code does:
user_input=""
: initializes the variable user_input
to an empty string.
while [ "$user_input" != "exit" ]; do
: starts a while
loop that continues as long as the value of user_input
is not "exit".
read -p "Enter 'exit' to quit: " user_input
: prompts the user to enter a value and stores it in the variable user_input
.
echo "Exit Successful"
: Prints "Exit Successful" after the while
loop exits, indicating that the user has entered "exit".
Functions
Functions in programming allow you to encapsulate a sequence of commands into a reusable block of code. They improve code readability, maintainability, and reusability by breaking down complex scripts into smaller, more manageable pieces.
As Martin Fowler aptly stated,
"Any fool can write code that a computer can understand. Good programmers write code that humans can understand."
You declare a function in Bash using the function
keyword followed by the function name and parentheses.
function my_function() {
# Function commands go here
}
Omitting the function
keyword also works
my_function() {
# Function commands go here
}
To invoke or call a function, you simply use its name
my_function() {
# Function commands go here
}
# function call
my_function
Functions can have arguments. You'll learn a way of passing arguments to bash scripts and functions from the following example.
greet() {
echo "Hello $1, nice to meet you!"
}
greet "Dan"
What do we have here?
In this example, the greet()
function takes one argument, $1
, which represents the first argument passed to the function. $2
represents the second, $3
represents the third, and so on.
When the function is called with greet "Dan"
, the string "Dan" is passed as an argument to the function. Inside the function, $1 is replaced with the value "Dan".
So if you wanted to write a function to pass your name and age as parameters and display them in a string, your function would look like this:
myself() {
echo "Hello I am $1, I am $2 years old"
}
myself "Fawz" 26
$1
and $2
are replaced by Fawz
and 26
respectively.
The return
statement
Bash functions do not have explicit return types, but they can return a value using the return statement. The return value is stored in the special variable $?
.
Write a function to add two numbers. Use the return
statement to return the result. Remember that you will need to use echo to display the result stored in the $?
variable.
function add() {
result=$(( $1 + $2 )) # Calculate the sum
return $result # Return the result
}
# Call the add function
add 5 3
echo "The sum is: $?"
# This will display "The sum is: 8"
Conclusion and Further Exploration
Congratulations! You've successfully conquered the basics of Bash scripting. You've learned how to navigate the command line, write scripts to automate tasks, and control the flow of your programs using variables, conditionals, and loops. This newfound power opens doors to a vast world of possibilities, from automating repetitive tasks to managing complex system configurations.
But this is just the beginning of your Bash scripting adventure! You can check out the following resources to fuel your exploration:
- Bash Guide: The official Bash documentation is a comprehensive resource for everything Bash-related: https://www.gnu.org/software/bash/manual/
- Free Bash Scripting handbook: This is an open-source introduction to Bash scripting guide/ebook that will help you learn the basics of Bash scripting: https://github.com/bobbyiliev/introduction-to-bash-scripting
- Learn Bash Scripting: This online tutorial offers a user-friendly introduction to Bash scripting concepts: https://github.com/freeCodeCamp/learn-bash-scripting-by-building-five-programs/blob/main/TUTORIAL.md
- Bash for Beginners: This freecodecamp video provides a step-by-step approach to learning Bash scripting: https://m.youtube.com/watch?v=tK9Oc6AEnR4
Feel free to experiment, explore different scripts, and don't be afraid to make mistakes. The programming community is vast and welcoming, so don't hesitate to seek help online if you get stuck.
Like and Comment!
Did you enjoy conquering the terminal with this tutorial? If you found this introduction to Bash scripting helpful, or if you have any questions or suggestions, leave a comment below! I'd love to hear your thoughts and experiences.
Thank you for reading!
Top comments (3)
Pretty complete. I would have suggested working with shellcheck and shfmt
koalaman / shellcheck
ShellCheck, a static analysis tool for shell scripts
ShellCheck - A shell script static analysis tool
ShellCheck is a GPLv3 tool that gives warnings and suggestions for bash/sh shell scripts:
The goals of ShellCheck are
To point out and clarify typical beginner's syntax issues that cause a shell to give cryptic error messages.
To point out and clarify typical intermediate level semantic problems that cause a shell to behave strangely and counter-intuitively.
To point out subtle caveats, corner cases and pitfalls that may cause an advanced user's otherwise working script to fail under future circumstances.
See the gallery of bad code for examples of what ShellCheck can help you identify!
Table of Contents
mvdan / sh
A shell parser, formatter, and interpreter with bash support; includes shfmt
sh
A shell parser, formatter, and interpreter. Supports POSIX Shell, Bash, and mksh. Requires Go 1.21 or later.
Quick start
To parse shell scripts, inspect them, and print them out, see the syntax examples.
For high-level operations like performing shell expansions on strings, see the shell examples.
shfmt
shfmt
formats shell programs. See canonical.sh for a quick look at its default style. For example:For more information, see its manpage, which can be viewed directly as Markdown or rendered with scdoc.
Packages are available on Alpine, Arch, Debian, Docker, Fedora, FreeBSD, Homebrew, MacPorts, NixOS, OpenSUSE, Scoop, Snapcraft, Void and webi.
gosh
Proof of concept shell that uses
interp
. Note that it's not meant to replace a POSIX shell at…Thank you so much for suggesting shellcheck and shfmt! Do you have any other tools you'd recommend for bash scripting?
Patience? 🤣😅
More seriously, shfmt and shellcheck are amazing.
You can find plugins for IDEike this one
github.com/vscode-shellcheck/vscod...
You could also use precommit hook, or github actions to run them when you commit or push