$echo 'message to print.'
The second method is the printf
command; this command is more flexible than the echo
command because it allows you to format the string that you want to print:
$printf 'message to print'
The previous formula is too simplified; in fact, printf
allows you to format strings as well (not just for printing; it's more than that). Let's look at an example: if we want to display the number of live hosts in a network, we can use the following pattern:
root@kali:~# printf "%s %d\n" "Number of live hosts:" 15 Number of live hosts: 15
Figure 2.1 Bash Scripting
Let's divide the command so you can understand what's going on:
%s : Means we're inserting a string (text) in this position
%d : Means we're adding a decimal (number) in this position
\n : Means that we want to go to a new line when the print is finished
Also, take note that we are using double quotes instead of single quotes. Double quotes will allow us to be more flexible with string manipulation than the single quotes. So, most of the time, we can use the double quotes for printf
(we rarely need to use the single quotes).
To format a string using the printf
command, you can use the following patterns:
%s : String (texts)
%d : Decimal (numbers)
%f : Floating‐point (including signed numbers)
%x : Hexadecimal
\n : New line
\r : Carriage return
\t : Horizontal tab
Variables
What is a variable, and why does every programming language use it anyway?
Consider a variable as a storage area where you can save things like strings and numbers. The goal is to reuse them over and over again in your program, and this concept applies to any programming language (not just Bash scripting).
To declare a variable, you give it a name and a value (the value is a string by default). The name of the variable can only contain an alphabetic character or underscore (other programming languages use a different naming convention). For example, if you want to store the IP address of the router in a variable, first you will create a file var.sh
(Bash script files will end with .sh
), and inside the file, you'll enter the following:
#!/bin/bash #Simple program with a variable ROUTERIP="10.0.0.1" printf "The router IP address: $ROUTERIP\n"
Let's explain your first Bash script file:
#!/bin/bash is called the Bash shebang; we need to include it at the top to tell Kali Linux which interpreter to use to parse the script file (we will use the same concept in Chapter 18, “Pentest Automation with Python,” with the Python programming language). The # is used in the second line to indicate that it's a comment (a comment is a directive that the creator will leave inside the source code/script for later reference).
The variable name is called ROUTERIP , and its value is 10.0.0.1.
Finally, we're printing the value to the output screen using the printf function.
To execute it, make sure to give it the right permissions first (look at the following output to see what happens if you don't). Since we're inside the same directory ( /root
), we will use ./var.sh
to execute it:
root@kali:~# ./var.sh bash: ./var.sh: Permission denied root@kali:~# chmod +x var.sh root@kali:~# ./var.sh The router IP address: 10.0.0.1
Congratulations, you just built your first Bash script! Let's say we want this script to run automatically without specifying its path anywhere in the system. To do that, we must add it to the $PATH
variable. In our case, we will add /opt
to the $PATH
variable so we can save our custom scripts in this directory.
First, open the .bashrc
file using any text editor. Once the file is loaded, scroll to the bottom and add the line highlighted in Figure 2.2.
Figure 2.2 Export Config
The changes will append /opt
to the $PATH
variable. At this stage, save the file and close all the terminal sessions. Reopen the terminal window and copy the script file to the /opt
folder. From now on, we don't need to include its path; we just execute it by typing the script name var.sh
(you don't need to re‐execute the chmod
again; the execution permission has been already set):
root@kali:~# cp var.sh /opt/ root@kali:~# cd /opt root@kali:/opt# ls -la | grep "var.sh" -rwxr-xr-x 1 root root 110 Sep 28 11:24 var.sh root@kali:/opt# var.sh The router IP address: 10.0.0.1
Commands Variable
Sometimes, you might want to execute commands and save their output to a variable. Most of the time, the goal behind this is to manipulate the contents of the command output. Here's a simple command that executes the ls
command and filters out the filenames that contain the word simple using the grep
command. (Don't worry, you will see more complex scenarios in the upcoming sections of this chapter. For the time being, practice and focus on the fundamentals.)
#!/bin/bash LS_CMD=$(ls | grep 'simple') printf "$LS_CMD\n"
Here are the script execution results:
root@kali:/opt# simplels.sh simpleadd.sh simplels.sh
Script Parameters
Sometimes, you will need to supply parameters to your Bash script. You will have to separate each parameter with a space, and then you can manipulate those params inside the Bash script. Let's create a simple calculator ( simpleadd.sh
) that adds two numbers:
#!/bin/bash #Simple calculator that adds 2 numbers #Store the first parameter in num1 variable NUM1=$1 #Store the second parameter in num2 variable NUM2=$2 #Store the addition results in the total variable TOTAL=$(($NUM1 + $NUM2)) echo '########################' printf "%s %d\n" "The total is =" $TOTAL echo '########################'
You can see in the previous script that we accessed the first parameter using the $1
syntax and the second parameter using $2
(you can add as many parameters as you want).
Let's add two numbers together using our new script file (take note that I'm storing my scripts in the opt
folder from now on):
root@kali:/opt# simpleadd.sh 5 2 ######################## The total is = 7 ########################
There is a limitation to the previous script; it can add only two numbers. What if you want to have the flexibility to add two to five numbers? In this case, we can use the default parameter functionality. In other words, by default, all the parameter values are set to zero, and we add them up once a real value is supplied from the