Special Variables in Bash Scripting

Reading Time: 4 minutes

Special variables are the variables that have a predefined meaning within a computer programming language. They are different in different languages but in this blog, we are going through the special variables in bash scripting.

List of special shell variables

These are the special shell variables that are set internally by the shell and which are available for the user:

VariablesDescription
$0The filename of the current script.
$1-$9Stores the names of the first 9 arguments or can be used as the arguments’ positions.
$$The process id of the current shell.
$#The number of arguments supplied to a script.
$*Stores all the command line arguments by joining them together.
$@Stores the list of arguments as an array.
$?Specifies the exit status of the last command or the most recent execution process.
$!Shows the id of the last background command.
$-Shows the options set used in the current bash shell.
List of special shell variable

Sample Script

Create a sample script to see how a special variable works. In this script, we are going to use $0, $1-$9, $$, $#.

#!/bin/bash

# sample.sh

echo "Process id of shell = $$"
echo "Name of shell script = $0"
echo "Number of args = $#"
echo "Argument 1 = $1"
echo "Argument 2 = $2"

Output

When we don’t give any argument other than file name so the output is:

$ ./sample.sh 
Process id of shell = 22337
Name of shell script = ./sample.sh
Number of args = 0
Argument 1 = 
Argument 2 = 

Since we didn’t provide any argument so the number of arguments is zero.

If we provide some arguments then the output will be:

$ ./sample.sh 1 2 3
process id of shell = 22342
Name of shell script = ./sample.sh
Number of args = 3
Argument 1 = 1
Argument 2 = 2

This is the basic example of using argument passing. Now, what if we provide more than 9 arguments then how can we use them in our script. So next we are going to discuss $@, $*, and ${}.

$?

The $? represents the exit status of the previous command.

Exit status is a numerical value returned by every command upon its completion. As a rule, most commands return an exit status of 0 if they were successful, and a positive value i.e 1 if they were unsuccessful.

knoldus@knoldus-Vostro-3559:~/bashspecialvar$ echo $?
0
knoldus@knoldus-Vostro-3559:~/bashspecialvar$ llaa
llaa: command not found
knoldus@knoldus-Vostro-3559:~/bashspecialvar$ echo $?
127

The return status of the previous command is successful, so it returns 0. Now we see the second command failed and the return status is 127 which means “command not found”.

$!

It returns the process id of the last background command:

knoldus@knoldus-Vostro-3559:~$ echo $!

knoldus@knoldus-Vostro-3559:~$ ls &
[1] 2907
knoldus@knoldus-Vostro-3559:~$ echo $!
2907

knoldus@knoldus-Vostro-3559:~$ cd &
[1] 2912
knoldus@knoldus-Vostro-3559:~$ echo $!
2912
[1]+  Done                    cd
knoldus@knoldus-Vostro-3559:~$ 

So in the above example, we see how we can return the process id of the previous background command. So here process id of ls the command is 2907 and the process id of cd the command is 2912.

$* and $@

$* and $@ special variables are used to take multiple arguments at a time. But there is some difference between them which is shown as:

  1. $* and $@ when unquoted are identical and expand into the arguments.
  2. “$*” is a single word, comprising all the arguments to the shell, joined together with spaces. For example ‘1 2’ 3 becomes “1 2 3”.
  3. “$@” is identical to the arguments received by the shell, the resulting list of words completely matches what was given to the shell. For example ‘1 2’ 3 becomes “1 2” “3”.
  4. In short, $@ when quoted (“$@”) breaks up the arguments if there are spaces in them. But “$*” does not break the arguments.

Let’s take an example to explain the above points.

#!/bin/bash

# variable arguments
# varArgs.sh

echo "argument length=${#@}"
echo "argument length=${#*}"
echo

for arg in $*
do
	echo "$arg "
done

echo

for arg in "$*"
do
	echo "$arg "
done

echo

for arg in $@
do
	echo "$arg "
done

echo

for arg in "$@"
do
	echo "$arg "
done

Let’s focus on the two outputs below to see the difference between $@ and $* :

Output:

1. first output when the argument is given as 1 2 3 4 5

$ ./varArgs.sh 1 2 3 4 5
argument length=5
argument length=5

1 
2 
3 
4 
5 

1 2 3 4 5 

1 
2 
3 
4 
5 

1 
2 
3 
4 
5 

2. Second output when the argument is given as 1 2 3 '4 5':

$ ./varArgs.sh 1 2 3 '4 5'
argument length=4
argument length=4

1 
2 
3 
4 
5 

1 2 3 4 5 

1 
2 
3 
4 
5 

1 
2 
3 
4 5 

Now you can see the difference between $@ and $* when used without quotes and with quotes. The difference is purely seen in the last line of both the output.

$-

$- (dollar hyphen) is a special variable that returns the flags used in the current Bash shell. $- contains the shell’s flags in use in the terminal.

Example

$ echo $-
569JNRXZghikms

You can test this by adding a flag using the set command:

$ set +J  # + removes the 'J' flag from list
$ echo $-
569NRXZghikms

$ set -J # - adds the 'J' flag in the list
$ echo $-
569JNRXZghikms

Extra tip

To use positional parameters above 9 you can use {} to extend the number as shown in the example below:

knoldus@knoldus-Vostro-3559:~/bashspecialvar$ cat posi.sh 
#!/bin/bash

# positional parameter
# posi.sh
echo "Number of parameter passed: $#"

echo "10th parameter is : ${10}"

echo "11th parameter is : ${11}"

Output for the above code is :

knoldus@knoldus-Vostro-3559:~/bashspecialvar$ ./posi.sh 1 2 3 4 5 6 7 8 9 10 11
Number of parameter passed: 11
10th parameter is : 10
11th parameter is : 11

This is how you can use positional parameters above 9.

Conclusion

In this blog we just learn how to use special variables in a bash script and also how can we access arguments passed through the command line.

This is the simple usage of special variables but we can do more than that. I hope this blog will help you to learn the basics of shell script.

Written by 

Himanshu is a Software Consultant[[Devops]] at Knoldus Software LLP. He loves to explore and learn new tools and technologies.