In today’s fast-paced world, automation has become essential for streamlining tasks and improving productivity. One powerful tool for process automation is Bash scripting. Bash (Bourne Again SHell), is a versatile scripting language commonly used in Unix-based systems. In this Bash scripting tutorial, I will explore the world of Bash scripting and its capabilities for automating various tasks efficiently. Let’s embark on a journey to becoming a proficient Bash scripter!
Introduction to Bash Scripting
Whether you’re a network engineer, developer, data analyst, system administrator, or just a random user looking for process-automating tasks, Bash Scripting is the powerful part that optimizes your working efficiency in all Unix-like environments including various Linux distributions, macOS, and other Unix-based systems.
Effectively, a Bash script is a plain text file loaded with a series of commands and computer programs written in the Bash programming language. Developers use Bash scripting to avoid repetitive tasks on the Linux filesystem and increase the efficiency of system administration, data deployment, automated backups, etc.
Why Use Bash Scripting?
Bash scripting is commonly used for a variety of purposes due to its flexibility and power in automating tasks. Exercising Bash scripting upgrades your command-line skills. Here’s why you should learn Bash scripting:
- Automation: To automate repetitive tasks and save time.
- Customization: To customize scripts as per preferences.
- Text Manipulation: To manipulate texts by performing operations like searching, extracting, and so on.
- Data Processing: To process the manipulated data effectively.
- System Administration: To maintain different configurations and servers.
- Efficiency: To handle multiple complex tasks within a single script.
Bash Scripting Basics
Bash scripting involves understanding fundamental concepts such as variables, control structures, functions, parameters, etc. Variables in Bash are used to store and manipulate data. You can assign values to variables and access them later in the script. Control structures, like conditional statements (if-else, case) and looping constructs (for, while), allow you to control the flow of execution and make decisions in your scripts. Functions provide modularity and code reusability by encapsulating a set of instructions that can be called multiple times.
A Subtle Overview of Bash Shell & Command Line Interface
The term ‘shell’ is a command-line interface (CLI) that provides an interaction between the operating system and the user. There are many shells available there such as Bash, Z shell (zsh), Korn shell (ksh), C shell (csh), Fish (Friendly Interactive Shell), etc. Among all, Bash is one of the most commonly used command-line interpreters which is an open-source GNU project. It is written by Brian Jhan Fox as an updated version of the Bourne Shell program ‘sh‘. This is the by-default login shell for most Linux distributions like Ubuntu, Debian, Fedora, CentOS, etc.
Bash Comments
In Bash scripting, comments are the lines that start with a hash symbol (#). Generally, comments are ignored by the Bash interpreter during the command execution. Though comments are not executable, they play a significant role in documenting the Bash codes. Have a look at the following commenting steps in Bash:
Commenting Steps at a Glance
- Create a file with a .sh extension.
- Open the file in any text editor like Nano, Vim, Emacs, etc.
- Append the following line at the beginning of the script that includes the Shebang/Hashbang (#!):
#!/bin/bash
- Then, write comments along with the programs in the script explaining the function of each coded line.
- Finally, save the script by clicking CTRL+S and exit by typing CTRL+X.
Categories of Comments
Bash commenting can be of different categories:
- Single-line comments: Comments placed at the start of a coded line with a # and extended to the end of the line.
- Inline comments: Comments placed at the end of a coded line with a #.
- Multiple-line comments: A series of single-line comments to explain a section of code.
- Block comments: Comments enclosed between the delimiter “: <<‘block_comment’” and “block_comment” to create a multiline comment block. It is recommended for larger documentation.
Concept of Variables & Data Types in Bash
Variables are the most important component in Bash that help to store, read, access, and manipulate data throughout the script. In Bash, there are no specific data types. A variable can hold any kind of data such as character strings, integers, float values, etc.
General Declaration & Assignment of Variable
A simple process for declaring and assigning variables:
- Selecting A Meaningful Variable Name: The foremost task is to name the variable appropriately with proper clarity of the function of the variable.
- Declaring the Variable: With the aid of the ‘declare command’, you can easily declare any variable explicitly in your script.
- Assigning Values to the Variable: The last task is to put a value to the declared variable. You can assign strings, numeric values, and boolean values to the specific variable.
A simple syntax to declare and assign values to a variable is:
declare variable1
variable1= 41
declare variable2
variable2= Linux
Accessing Variables Using ‘$’
Whenever you feel to access and see a variable, just append a ‘$ (dollar)’ symbol before the variable along with the echo command just like the following:
echo $variable1
echo $variable2
Another form to access a variable is ‘${variableName}’. This syntax is suitable for confusing situations regarding variable names. For example:
variable=Lin
echo The website is ${variable}uxSimply
Variable Scopes – Global VS Local
In Bash scripting, variables include different scopes. Among them, the two prominent types of variable scopes are global and local.
A. Global Variable
In general, every variable you create in Bash is a global variable which means you can use them in any function, conditional statement, or loop, and access them from anywhere in the script.
B. Local Variable
The local variables are only confined to the blocks of code or functions where they are already declared. Bash doesn’t understand local variables outside of those blocks. Basically, to create a local variable, you need to use the term ‘local’ before the variable name.
Some Variable Types
In Bash, there may be a series of variables of different types. Each type serves a specific purpose in Bash scripting like below:
- The Predefined variables by the Bash shell.
- Example: $HOME (User’s home directory), $PWD (User’s current working directory).
- These variables store information about the environment.
- Example: $PATH (The directories where executable files are located).
- These variables hold any kind of text data.
- Example: $name (User’s name), $designation (User’s designation).
- Array variables capture multiple values as an array.
- Example: ${array[@]} (The array elements).
- Every special variable has a special & specific meaning.
- Example: $? (Exit status of the last command), $0 (Name of the executing script).
- These are not directly included in Bash, yet you can simulate them by using strings (true or false) or integers (0 for false or true for otherwise).
- These variables use the HereDoc construct to input multiline text.
Bash Quotes
Quotes are an important element in Bash that you can use to determine and manipulate strings. Typically, Bash uses spaces to determine separate values. So, while working with variables to store complex values, enclose your content in quotes that consider the enclosed contents as a single item. Here’s a summary of three quoting mechanisms in Bash:
1. Single Quotes:
- Preserve the literal value of each character of the enclosed string.
- No variable expansion occurs.
name="A"
echo 'Hello, $name!'
#Output: Hello, $name!
2. Double Quotes:
- Preserve the literal value of all characters within the enclosed string.
- Allow variable expansion.
- Variables within quotes are replaced with their values.
name="A"
echo "Hello, $name!"
#Output: Hello, A!
3. Escape Quotes:
- Use a backslash (\) before a literal quote character within a string enclosed by the same type of quotes.
- Prevents the shell from interpreting the literal quote as the end of the string.
echo 'I\'m here.'
#Output: I'm here.
Bash Parameters
In Bash scripting, a Bash parameter is the fundamental feature that allows Bash scripts to receive inputs from the command line and modifies the scripts’ responses according to those inputs. Parameters can easily be referred to as command-line arguments that commonly indicate a piece of information or values that make your scripts more adaptable and user-friendly by passing these values to the scripts during execution.
Here are a few parameters to get familiar with:
- Positional Parameter: Positional parameters refer to a set of variables that holds values when a script is invoked. You can access these parameters by using the special variables: $1, $2, $3, and so on.
- Optional Parameter: You can provide specific options, implement optional parameters, and get the script’s response accordingly. Also, you can often identify optional parameters by short (preceeding -) or long options(two preceeding dashes –).
- Special Parameter: Bash special parameters are the values that retain specific information such as the name of the script, the exit status of the recent command, and the number of arguments passed to the script, etc.
Bash Expansion
Bash Expansion is the process of altering text using various mechanisms or constructs imparted by the Bash shell. These mechanisms let users manipulate variables, strings, and other input data. Some mostly used Bash expansions:
- Brace Expansion: A powerful feature, Brace expansion allows you to generate strings by specifying a set of values enclosed in curly braces ‘{}’. It lets you write more compact scripts.
- Tilde Expansion: Tilde expansion provides a convenient way to quickly navigate to specific users’ home directories only by using the ‘~’ character, instead of typing the full paths.
- Parameter Expansion: Parameter Expansion simply defines the way of accessing the value of any variables in Bash.
- Variable Expansion: Variable expansion is the fundamental feature in Bash that allows you to work with dynamic data by substituting variable names with their actual values.
- Arithmetic Expansion: This expansion is a way to perform mathematical operations in a script. The proper syntax for this expansion is $((expression)).
- Glob Expansion & Wildcard Expansion: Glob expansion (also known as Filename expansion) is a broader concept of matching files based on some specific patterns or criteria by using some wildcard characters like ?, *, [..] where you need not list any filename individually. On the contrary, Wildcard expansion is a more specific term that is directly related to the wildcard characters.
Some other Bash expansions are- Shell expansion, History expansion, Array expansion, etc.
Bash I/O
Basically, there are a bunch of Bash commands that print out information to the terminal. While working on this shell, there are many times when you would like to save the output or pass the output as the input of another command. Being a shell, Bash supports these I/O-related tasks for creating a user-friendly environment between users and the script.
Bash Standard Streams (stdin, stdout, stderr)
Streams refer to a continuous flow of data that either receives texts in or feeds texts out ceaselessly. These are the special channels that handle various input and output operations like data capturing, manipulating, redirecting, appending, etc.
3 Special File Descriptors
In Bash and other Unix-like systems, every stream is identified by a file descriptor. As everything in Linux is assumed as files, it includes input and output too. Typically, the system allows each process to have up to nine open file descriptors. Among them, Bash reserves only the first three descriptors with their specific IDs. Here are the three standard streams with their IDs (file descriptors ‘0’, ‘1’, ‘2’) that you can access whenever a process starts:
- stdin: It continuously receives input data and can be redirected from other commands and files.
- stdout: It displays output continuously and can be redirected to files and other commands.
- stderr: It displays error messages and can be redirected to files and other commands.
Bash Redirection
Redirection in Bash is a method of changing the sources and destinations of standard input, standard output, and standard error flexibly. Bash executes redirection which is useful for capturing input data from files, holding output, and handling errors. There are some redirection operators below with their basic syntaxes:
Redirecting Standard Input → ‘<’
- Redirects the input of a command from a file despite typing manually.
command < input_file.txt
Redirecting Standard Output → ‘>’
- Redirects the output of a command to a file rather than displaying it on the terminal.
- Overwrites the file.
command > output_file.txt
Appending Standard Output → ‘>>’
- Appends the output of a command to an existing file without overwriting its contents.
command >> output_file.txt
Redirecting Standard Error → ‘2>’
- Redirects error messages produced by commands.
command 2> error.log
Appending Standard Error → ‘2>>’
- Appends error messages to an existing file without overwriting its content.
command 2>> error.log
Redirecting Both Standard Output and Standard Error
- Redirects both output and error using the ‘&>’/‘>&’/‘2>&1’ symbol.
command 2>&1 > output.log
Appending Both Standard Output and Standard Error
- Appends both output and error without overwriting using the ‘>>‘ symbol.
command 2>&1 >> output.log
Bash Piping
Piping is the core process of chaining together the standard output of one command with the standard input of another command to perform complex tasks. By using the Unix pipe character ‘|’, you can create command sequences.
Basic Syntax:
Command 1 | Command 2 | Command 3
Bash Operator
In Bash, operators are the characters or symbols that perform multiple operations on values, variables, and various types of expressions. Depending on what type of output you want from your scripts, you need to append operators within codes. Below are some basic operators in Bash:
1 Arithmetic Operators: Arithmetic operators perform simple mathematical expressions.
- Addition (+)
- Subtraction (-)
- Multiplication (*)
- Division (/)
- Modulus (%)
- Exponentiation (**)
2. Logical/Boolean Operators: Logical operators perform logical operations.
- Logical AND (&&)
- Logical OR (||)
- Logical NOT (!)
3. Comparison Operators: Comparison operators compare expressions and evaluate their relationships. These are generally used in conditional statements and loops.
- Equal to (-eq)
- Not equal to (-ne)
- Less than (-lt)
- Less than or equal (-le)
- Greater than (-gt)
- Greater than or equal (-ge)
4. String Operators: String operators manipulate and compare strings.
- Equal to (=)
- Not equal to (!=)
- If the string is empty (-z)
- If the string is non-empty (-n)
- Concatenation (str1$str2)
5. Unary Operators: Unary operators perform specific operations on a single value or operand.
- Increment by 1 (++)
- Decrement by 1 (–)
6. File Test Operators: File test operators perform tests on files and directories & to determine their properties. These are often used in conditional statements to make decisions regarding files and directories.
- File existence test (-e)
- Regular file test (-f)
- Block special file test (-b)
- Character special file test (-c)
- Non-empty file test (-s)
- Directory test (-d)
- Read permission check (-r)
- Write permission check (-w)
- Execution permission check (-x)
Bash Conditional Statements
Conditionals make your Bash scripts more versatile by allowing you to make decisions while executing different codes based on certain data or conditions in Bash. Generally, Bash offers various types of statements like if, if else, else if (elif), etc. These statements enable different actions depending on the multiple outcomes of the conditional tests in Bash.
Different Types of Conditional Statements With Their Simple Structures
A shorthand list of different conditional statements with their basic visual structures is given below:
Conditional Statements | Simple Structure |
---|---|
if | if [ condition ]; then #Code to execute fi |
Nested if | if [ condition ]; then if [ another_condition ]; then #Code to execute fi fi |
If else | if [ condition ]; then #Code to execute else #Another code to execute fi |
Else if | if [ condition ]; then #Code to execute elif [ another_condition ]; then #Code to execute else #Code to execute fi |
case | case “$variable” in pattern1) #Write code when pattern1 matches ;; pattern2) #Write code when pattern2 matches ;; *) #Write code when no patterns match ;; esac |
Bash Loops
Loops are the essential tool in Bash used for automating the tasks that need repetition. You can efficiently process data and handle different scenarios by taking a set of commands and running them multiple times until you reach the desired result.
Basic Loop Structures
Following are three basic loop structures that you can use to perform the loop operations in Bash scripting:
A. For Loop
The for loop iterates over the sequence of values like arrays, range of numbers, or list of items.
Basic Syntax:
for variable in values;
do
#Command
done
B. While Loop
The while loop is one of the easiest loops to work with in Bash. As long as the applied condition evaluates to true, the while loop repeatedly executes the given set of commands.
Basic Syntax:
while [ condition ];
do
#Command
done
C. Until Loop
The until loop is quite similar to the while loop. The only difference is it executes the given set of commands until the applied condition becomes true.
Basic Syntax:
until [ condition ];
do
#Command
done
Loop Control Statements
Following are three control statements that you can use to perform the loop operations in Bash scripting:
- break: The break statement tells Bash to leave the loop straight away when a specific condition is met.
- continue: The continue statement tells Bash to skip the current iteration of the loop and proceed to the next iteration.
- exit: The exit statement terminates the entire shell session.
Bash Array
Arrays are data structures that contain multiple values under a single variable. You can use any variable as an array in Bash. Each and every value an array holds is known as an element. It’s not necessary that the elements must be of similar type. Bash supports both associative arrays (Strings) and indexed arrays (Numerical indices: 0,1,2,3,..) and there is no limited size of the arrays.
In Bash scripting, arrays provide a convenient way to store, and manage collections of data, and also, retrieve elements in a list format for performing specific operations. Actually, arrays are zero-based meaning that the first element of the array is indexed with ‘0’. Here is a little outline of how you can declare and work with Bash arrays:
- Declaring Array: Use the built-in ‘declare’ command for an explicit declaration of an array.
- Printing Array Elements: After array declaration, use the syntax ‘${array_name[@]}’ to print and display all the array elements space-separated where ‘[@]’ represents the index.
- Iterating over Array: Use any loops to iterate over array elements.
- Inserting and Deleting Elements from Array: Add and delete elements from an array by setting the proper index of the element and using the ‘unset’ command respectively.
Bash String
In Bash scripting, strings are the fundamental data types used to store text-based data. These are the sequence of characters including letters, symbols, and spaces. Bash strings also contain numbers or digits enclosed in single quotes (‘) or double quotes (”). They play a crucial role in manipulating text and serving several purposes like processing user input, storing path information, etc. Here are some basic string operations in Bash:
- Defining String: Use single or double quotes to define strings. You can omit the quotes too, but there can’t be any space either before or after the equal (=)
- Reading String from User: Using the ‘read’ command, you can read the inserted input string of the user.
- String Concatenation: You can perform string concatenation by using the ‘+’ operator or listing the strings in order.
- String Length: You can find the length of a string by the placing ‘#’ operator inside the parameter expansion (curly braces) before the variable name like ‘${#variable}’.
- Substring Extraction: The syntax ‘${string:start:length}’ might help you to extract a substring from a string.
- Comparing Strings: By using the comparison operators you can compare strings.
Bash Functions
In Bash, a function is essentially a reusable set of commands under one name that you can call multiple times within your script. Whenever you need to perform certain tasks several times, instead of writing the codes repeatedly, you can write them once in a function and call that function multiple times.
The Bash function really helps break down your scripts into smaller ones and make them more manageable and organized. Elementally, it’s more like a script within a script.
Now, take a look at how you can define and use functions in Bash:
A. Declaring Function
You can define functions in two formats:
Format 1 > Mostly used format
function_name () {
commands
}
Format 2 > Using the reserved word ‘function’
function function_name {
commands
}
B. Calling Function
When you declare a function, it doesn’t execute. It only executes when called after the declaration. So, call a function by simply writing its name and then execute the coded lines within it.
C. Passing Arguments
It’s so obvious to like a function to process data. For this, you need to pass input arguments to the function. No worry! Passing input data to a function is no different from passing command line arguments to a Bash script.
Insert the parameters directly just after the function call and put spaces between the function name and the parameters. Also, you can use the arguments within double quotes to prevent unexpected errors in the Bash script. Moreover, to access the arguments within the function, you can use some special variables like $0, $1, $2, $*, $@, $#, etc.
D. Return Values
When it comes to returning values, Bash functions differ from other programming languages. By default, Bash functions return the exit status of the last executed command to verify whether the function was successfully executed or not. Hereafter, you can use the keyword ‘return’ and the special variable ‘$?’ to indicate and capture the return values of the functions respectively in Bash.
Bash Files & Directories
In Bash scripting, working with files and directories is a very common task. A File refers to the fundamental unit of data storage including text, program, binary data, configuration settings, etc. Let’s have a look at the key aspects of Bash files!
What is a File System?
A file system in Bash is a tree-like structure organized with a collection of files and folders. Below is a representation of a hierarchical file system topology:
File Types
There are various types of files in Bash. Here are some common file types:
- Regular File (-): It contains data, text, images, etc.
- Special File: It specifies and gives access to the hardware devices. Such as device files, sockets, named pipes, etc.
- Symbolic Link (l): It points to other files or directories.
- Directory (d): It contains both regular and special files forming a hierarchy.
Navigating Operations
Here are some commonly used commands that you can use to perform navigating operations on Bash files & directories:
- cd: Change the directory.
- ls: List files.
- cat: Display file contents.
- touch: Create files.
- mkdir: Create directories.
- cp: Copy files.
- mv: Move or rename files.
- rename: Rename files.
- rm: Remove files & directories.
- rmdir: Remove empty files & directories.
File Permissions
In Linux-based systems, file permissions are an essential feature to secure its filesystem. File permission actually depicts who can read, write, or execute a file or directory. Generally, you can represent file permissions using the octal values or a series of characters (typically, by a 10-character string) by appending various commands. Explore the following overviews of how file permissions work in Bash:
Ownership Category
Three primary categories of Linux users:
- Owner/User: The user who creates or owns the file or directory.
- Group: A group of users can access permissions associated with a file.
- Others: Any third-party users who are not the owner or part of the group.
File Permission Type
For each ownership category, there are three types of file permissions:
- Read (r)
- Write (w)
- Execute (x)
Changing File Permissions
You can easily alter file permissions using the chmod command (change mode). You can specify permissions either in symbolic (symbols) or numeric (numbers) form.
Symbolic Form >
chmod u+x, o+rw file.txt
- chmod: Changes file permissions.
- u+x, o+rw: Adds execute (x) permission for user (u), and read-write (rw) permissions for others.
- file.txt: The file name.
Numeric Form >
chmod 644 file.txt
- 644: Sets read (r) and write (w) permission for owner, and read-only for group and others.
Visit the guide Change Permissions of Directories and Files Recursively with “chmod” to clearly understand File permissions in Bash.
File Extension
A file extension is the part of a filename that indicates the type of the file and the program you should start to open the file. Some common file extensions:
- .txt: Text file.
- .sh: Shell script file.
- .log: Log file.
- .conf: Configuration file.
Bash Error Handling
When it comes to Bash scripting, it’s very important to make the script error-free while executing it. Without proper error handling, Bash scripts may stop executing and fail to provide useful information to the users which makes it more difficult to troubleshoot. Look at the following part to figure out some best practices for error handling:
- Detecting Exit Status: When the exit status of a command is zero, it means there is no error. On the contrary, if there are any errors, the exit status shows some non-zero value. So, by checking the values of the exit status you can determine if the command was successfully executed or not.
- Using ‘if’ Conditional Statements: You can check the exit status of specific commands by using the ‘if’ statements and take proper actions.
- Using ‘set -e (errexit)’ and ‘set -u (nounset)’ Options: In Bash, the ‘set -e’ option tells to exit the script instantly if a command returns any non-zero exit status. The ‘set -u’ option tells Bash to exit if any uninitialized variables are encountered. However, by using these options judiciously, your script will automatically exit if any errors occur which will help you to prevent further issues.
- Using ‘set -v (verbose)’ Option: Though the ‘set -v’ option does not affect error handling directly, it can help in debugging. You can enable the verbose mode by using the ‘set -v’ option which means the Bash will print commands before their execution for debugging purposes.
- Using ‘trap’ Command: The ‘trap’ command allows you to specify a set of commands to be executed when your script receives specific signals or exits. You can use this command to detect errors and perform cleanup tasks.
- Using Error Messages: Error messages are a fundamental aspect in case of error handling. These can help you find what went wrong with the Bash users or administrators and aid in debugging. You can use the echo command to print error messages in bash scripts.
Conclusion
To wrap up, the bash scripting tutorial covers a wide range of topics related to automating tasks for Unix-like environments. Moreover, mastering Bash scripting is such a valuable skill that will help you to interact with your command line interface in a productive way and apply your knowledge to real-world cases.
People Also Ask
How do I start Bash scripting?
Starting with Bash scripting is a great way to automate tasks and enhance your efficiency on Unix-like systems. Here are steps to help you get started with Bash scripting:
- First, learn the basics of bash. Familiarize yourself with basic Bash commands and concepts.
- Then, understand shell scripting basics.
- After that, set up a text editor for writing your scripts. Popular choices are Vim, Emacs, Nano, etc.
- Write your first Bash script, let’s say in the Nano editor. One simplest script to write is:
#! /bin/bash
echo "Hello, World!"
- Now, save the script & exit the Nano editor.
- Finally, to execute the script type
bash script.sh
. - For advanced learning later introduce yourself with variables, conditional statements, loops, functions, etc.
Is Bash scripting easy?
Yes, in general when it comes to simple tasks and automation, a lot of new users find bash scripting easy to learn and use. However, as with any other programming language, the difficulty may increase with the complexity of the tasks you aim to cover.
What is Bash scripting tutorial?
A bash scripting tutorial is a learning resource designed to teach individuals how to write scripts using the bash programming language. These tutorials typically cover various aspects of bash scripting, starting from the basics and progressing to more advanced topics.
Where can I learn bash scripting?
There are various online resources where you can learn Bash scripting. Some of the popular platforms and websites are the official bash documentation (GNU Manual), online tutorials (W3Schools, LinuxSimply, Tutorialspoint, and Shell Scripting Tutorial), and YouTube, books, Bash Academy, etc.
Is Bash a good skill?
Yes, Bash scripting is a good skill for any developer, system administrator, or power user who wants to automate repetitive tasks and make their workflow more efficient.
Related Articles
- Introduction to Bash Scripting
- Bash Scripting Basics
- Bash Comments
- Bash Variables
- Bash Quotes
- Parameters in Bash Scripting
- An Overview of Shell Expansion in Bash
- Bash I/O
- Bash Redirection and Piping
- Bash Operator
- Bash Conditional Statements
- Loops in Bash
- Bash Array
- Bash String
- Bash Functions
- Bash Files and Directories
- Bash Error Handling and Debugging
- Bash Process and Signal Handling
FUNDAMENTALS A Complete Guide for Beginners
Can I copy to my personal notes ?