Just like any programming languages, we start off by data and variables. Here you'll learn the basic about BASH variables, how to create, read, update and delete data variables. Once we're done, we'll look into best practices and pre-defined variables.
BASH is a primitive tool that has supports over:
string
integer
boolean
The common ground rule for BASH is that, everything is a string. Hence, say you have an integer variable like:
i=0
The way to use is, say by comparison, is:
[[ "$i" == "0" ]]
Notice that $i
is converted into string.
However, because BASH supports integer
and boolean
, you can also do:
[[ $i == 0 ]]
[[ $b == true ]]
This is usable but not entirely recommended since variable in BASH is chaotic and not type-specific. That means any variable can be overridden by any new value type. Hence, you won't be surprised to get caught up by $i
is a boolean
.
Due to the type-nature of the variable in BASH, it is always converted to string before use. This way, we can ensure the data is always string, even for undefined or empty variables.
Variables in bash is quite easy to create, read, update and delete (CRUD). We'll look into each actions specifically in this portion. Variables are usable in a crude terminal command outside the script as well.
Creating a variable in bash is very straight-forward using "=
" sign, no space before, no space after. Example, say we can to create a person variable with the name James. It is:
person="James"
NOTE:
Now that we have a variable created, we want to read its value in order to use it. To do so, we use the dollar sign ($
) to call the variable value:
"$variable"
So, based on the example above, say we want it to print it out with echo, we get:
$ echo "$person"
James
NOTE:
-
) as an argument indicator.$ command="ls -la"
$ $command "$HOME"
total 632
drwxr-xr-x+ 44 holloway holloway 4096 Dec 9 14:18 .
drwxr-xr-x 3 root root 4096 Aug 12 17:00 ..
drwxr-xr-x 8 holloway holloway 4096 Aug 17 18:52 .atom
-rw------- 1 holloway holloway 32808 Dec 9 14:18 .bash_history
-rw-r--r-- 1 holloway holloway 220 Aug 12 17:00 .bash_logout
-rw-r--r-- 1 holloway holloway 4893 Oct 10 20:26 .bashrc
drwxr-xr-x 2 holloway holloway 4096 Sep 4 12:21 bin
...
$ command="ls"
$ $command "$HOME"
bin Desktop Music Public src
...
Say we want to update a variable value, since BASH is not typed-specific, you simply re-create the variable to update it. Following the example above, say we want to change into Sarah, you do:
person="Sarah"
If you read it again with "echo
" like the command above, you will see that $person
is now changed to Sarah.
$ echo "$person"
Sarah
In situation where we want to delete a variable, simply use unset
command to remove it. Example:
unset person
Once you're done, if you try to read the variable again, you get nothing as value.
IMPORTANT NOTE:
$
) when you perform unset
. Now that you know how to CRUD a variable, you need to know there are special variables that is preset for certain functions like $PATH
, $XDG_DATA_DIRS
, etc. Therefore, you must do a simple research on whether a variable name is preserved for special use (usually you can google it out easily). We'll cover those common special variables in the sub-section.
For now, you must be aware that you can't simply name a variable. Overriding these special function variables can lead to catastrophic effects.
Example, deleting the PATH variable leads to (A LOT of) missing commands! This is because terminal use PATH to search for executables which is the foundation of your terminal commands.
There are situations where you want to set a default value or to raise an error for variable that is unset or empty. Instead of adding a condition checking, you can make use of implicit variable expansions. There are a huge list of it but these are commonly used versions.
TIP:
You don't need to memorize or to use all. These are some extras. You'll be surprised that the most commonly used are only: set default values and use alternative values.
${variable-value}
value
if variable
is unset.${variable:-value}
value
if variable
is unset or empty.Example:
without colon:
# a is not set
$ unset a
$ echo "a is now: ${a-xyz}" && echo "a is set to: $a"
a is now: xyz
a is set to:
$
# a set and null (empty)
$ a=
$ echo "a is now: ${a-xyz}" && echo "a is set to: $a"
a is now:
a is set to:
$
# a is set
$ a=def
$ echo "a is now: ${a-xyz}" && echo "a is set to: $a"
a is now: def
a is set to: def
$
with colon:
# a is not set
$ unset a
$ echo "a is now: ${a:-xyz}" && echo "a is set to: $a"
a is now: xyz
a is set to:
$
# a set and null (empty)
$ a=
$ echo "a is now: ${a:-xyz}" && echo "a is set to: $a"
a is now: xyz
a is set to:
$
# a is set
$ a=def
$ echo "a is now: ${a:-xyz}" && echo "a is set to: $a"
a is now: def
a is set to: def
$
${variable=value}
value
if variable
is unsetvariable
to have value
variable
remains as empty.${variable:=value}
value
if variable
is unset or empty.variable
to have value
Example:
without colon:
# a is not set
$ unset a
$ echo "a is now: ${a=xyz}" && echo "a is set to: $a"
a is now: xyz
a is set to: xyz
$
# a set and null (empty)
$ a=
$ echo "a is now: ${a=xyz}" && echo "a is set to: $a"
a is now:
a is set to:
$
# a is set
$ a=def
$ echo "a is now: ${a=xyz}" && echo "a is set to: $a"
a is now: def
a is set to: def
$
with colon:
# a is not set
$ unset a
$ echo "a is now: ${a:=xyz}" && echo "a is set to: $a"
a is now: xyz
a is set to: xyz
$
# a set and null (empty)
$ a=
$ echo "a is now: ${a:=xyz}" && echo "a is set to: $a"
a is now: xyz
a is set to: xyz
$
# a is set
$ a=def
$ echo "a is now: ${a:=xyz}" && echo "a is set to: $a"
a is now: def
a is set to: def
$
${variable?value}
variable
is not set, exit and raise error with value
as the error message.${variable:?value}
variable
is unset or empty, exit and raise error with value
as the error message.Example:
without colon:
# a is not set
$ unset a
$ echo "a is now: ${a?xyz}" && echo "a is set to: $a"
bash: a: xyz
$ echo "$?"
1 # error
$
# a set and null (empty)
$ a=
$ echo "a is now: ${a?xyz}" && echo "a is set to: $a"
a is now:
a is set to:
$ echo "$?"
0 # OK
$
# a is set
$ a=def
$ echo "a is now: ${a?xyz}" && echo "a is set to: $a"
a is now: def
a is set to: def
$ echo "$?"
0 # OK
$
with colon:
# a is not set
$ unset a
$ echo "a is now: ${a:?xyz}" && echo "a is set to: $a"
bash: a: xyz
$ echo "$?"
1 # error
$
# a set and null (empty)
$ a=
$ echo "a is now: ${a:?xyz}" && echo "a is set to: $a"
bash: a: xyz
$ echo "$?"
1 # error
$
# a is set
$ a=def
$ echo "a is now: ${a:?xyz}" && echo "a is set to: $a"
a is now: def
a is set to: def
$ echo "$?"
0 # OK
$
${variable+value}
value
instead.${variable:+value}
variable
is set, use value
instead.variable
is unset or empty, remain empty.Example:
without colon:
# a is not set
$ unset a
$ echo "a is now: ${a+xyz}" && echo "a is set to: $a"
a is now:
a is set to:
$
# a set and null (empty)
$ a=
$ echo "a is now: ${a+xyz}" && echo "a is set to: $a"
a is now: xyz
a is set to:
$
# a is set
$ a=def
$ echo "a is now: ${a+xyz}" && echo "a is set to: $a"
a is now: xyz
a is set to: def
$
with colon:
# a is not set
$ unset a
$ echo "a is now: ${a:+xyz}" && echo "a is set to: $a"
a is now:
a is set to:
$
# a set and null (empty)
$ a=
$ echo "a is now: ${a:+xyz}" && echo "a is set to: $a"
a is now:
a is set to:
$
# a is set
$ a=def
$ echo "a is now: ${a:+xyz}" && echo "a is set to: $a"
a is now: xyz
a is set to: def
$
Variables can be externally or internally usable through its visibility. An externally usable variables means the variable retains its values even after the bash script is ended or any child process it forks can use the value; an internally usable variables means the variable is only usable within the bash script.
The purpose?
For security purposes, all default BASH variable starts as internally usable only. That means it is limited to that particular bash session (or terminal session).
To make an externally visible or usable variable, you can proceed to export
it. Keep in mind that there is no standard way to un-export
a variable. The only way is to delete the variable and re-create it without export. Here is an example:
$ export person="James"
It is always a good practice to split a process from the variable export. The reason is due to overlapping/masked value caused by the execution itself. Another reason is that it may disrupts test tool from analyzing your bash script properly. Here's an example, instead of doing this in one-line:
$ export person="$(cat ./james.name)" # bad example
You do:
$ person="$(cat ./james.name)"
$ export person
NOTE:
$
), just like the export person
above.Here is an example of a bash script, with a default valued variable to "Sarah" if the variable is unassigned or empty:
#!/bin/bash
echo "Hello! This person is: ${person:-Sarah}"
And if we execute it, we get:
$ ./demo.sh
Hello! This person is: Sarah
$
If we proceed to create internal variable, we'll immediately notice that the child process (the script) can't read the internal variable of your terminal session:
$ person="James"
$ ./demo.sh
Hello! This person is: Sarah
$
If we proceed to make the variable external, we can see the child process is able to read the variable:
$ export person
$ ./demo.sh
Hello! This person is: James
$
If we proceed to delete the exported variable, we see that the child process reverts back to its default variable.
$ unset person
$ ./demo.sh
Hello! This person is: Sarah
$
Now that you know the basic of about variable, how data is operated in BASH, how to CRUD a variable, set a default value, differentiate external and internal variables, we can proceed to look into the advanced variable features in the sub-topics section.