Script Parameters
Learn how to change the Bash script's behavior using parameters.
We'll cover the following
Parametrizing the photo directory
Let’s suppose we moved our photos from the ∼/photo
directory to ∼/Documents/Photo
. If we want to support the new path in the backup script, we should change its code. The following shows how the new script looks:
#!/bin/bash
tar -cjf ~/photo.tar.bz2 ~/Documents/Photo &&
echo "tar - OK" > results.txt ||
{ echo "tar - FAILS" > results.txt ; exit 1 ; }
cp -f ~/photo.tar.bz2 ~/backup &&
echo "cp - OK" >> results.txt ||
! echo "cp - FAILS" >> results.txt
Every time we move the photos from one directory to another, we have to change the script. This is inconvenient. A better solution is to make a universal script that can handle any directory. Such a script would receive the path to photos as an input parameter.
When we run a Bash script, we can pass command-line parameters there. This works the same way as for any GNU utility. We specify the parameters separated by a space after the script name. Bash will pass them to the script. Here is an example:
./photo-backup.sh ~/Documents/Photo
This command runs our script with the ~/Documents/Photo
input parameter. We can read it via the $1
variable in the script. If the script receives more parameters, we read them via the variables $2
, $3
, $4
, etc. These names match the numbers of the parameters. Variables of this type are called positional parameters.
There is a special positional parameter $0
. It stores the path to the launched script. It equals ./photo-backup.sh
in our example.
Let’s handle the input parameter in our script. The following shows how it looks after the change:
#!/bin/bash
tar -cjf ~/photo.tar.bz2 "$1" &&
echo "tar - OK" > results.txt ||
{ echo "tar - FAILS" > results.txt ; exit 1 ; }
cp -f ~/photo.tar.bz2 ~/backup &&
echo "cp - OK" >> results.txt ||
! echo "cp - FAILS" >> results.txt
The $1
variable stores the path to the photos. We use it in the tar
call. There are double quotes around the variable name. They prevent the word splitting mechanism.
Let’s suppose we want to archive photos from the ~/photo album
path. Then, we call the script this way:
./photo-backup.sh "~/photo album"
Let’s suppose that we skip double quotes around the variable name when we call the script. Then the tar
call looks like this:
tar -cjf ~/photo.tar.bz2 ~/photo album &&
echo "tar - OK" > results.txt ||
{ echo "tar - FAILS" > results.txt ; exit 1 ; }
In this case, the tar utility receives the ~/photo album
string in parts. It gets two parameters instead of one: ~/photo
and album
. These directories do not exist. Therefore, the script fails.
It is not enough to put parameters in double quotes when calling a script. We should quote all occurrences of the corresponding variable name in the script. This happens because of the way Bash runs a program.
Let’s suppose that we call a script from the shell. Then, Bash spawns a child process to execute it. The child process does not receive quotes from the command line because Bash removes them. Therefore, we should add quotes again inside the script.
Now, our backup script can handle the input parameter. What are the benefits of this solution? It provides us a universal script for making backups. The script can process any paths and types of input files: documents, photos, videos, source code, and so on.
However, adding parameter processing to our script leads to one problem. Let’s suppose we call it twice to makebackups of our photos and documents like this:
./photo-backup.sh ~/photo
./photo-backup.sh ~/Documents
The first command creates the ~/photo.tar.bz2
archive and copies it to the ~/backup
directory. Then, the second command does the same and overwrites the existing ~/backup/photo.tar.bz2
file. This way, we lose the result of the first command.
Get hands-on with 1400+ tech skills courses.