1. Overview

The dollar sign ($) plays a crucial role in shell scripting. This ranges from argument handling to process management, and even providing information about the script.

In this tutorial, we’ll explore the significance of each special dollar sign variable. First, we’ll discuss them in categories based on their function. After that, we’ll take a look at all of them side by side in a table.

2. Script Information

The shell environment provides special variables that offer insight into script execution and the broader shell context. We’ll look at two such variables: $0 and $_.

2.1. The $0 Variable

The $0 variable holds the name of the script itself, the one we’re currently executing:

$ echo "This script is called: $0"
This script is called: /usr/bin/zsh

It’s particularly useful for tasks like logging or debugging, conditional execution, and so on.

For instance, we can print $0 to identify the script involved in an operation or error message:

$ cat script_name.sh   
#!/bin/bash
echo "This script is called: $0"

Running this script gives the script name:

$ bash script_name.sh    
This script is called: script_name.sh

Consequently, it’s possible to control specific behavior within the script based on the script name:

$ cat script_name.sh     
#!/bin/bash

if [[ $0 == "script_name.sh" ]]; then
  # perform a certain action
fi

We can add a command to carry out some action based on the script name.

2.2. The $_ Variable

The $_ variable has a more dynamic nature. Initially, it holds the absolute path of the script or shell being invoked. However, its value changes after each command execution.

It becomes the last argument passed to the previous command:

$ cd Desktop        
$ echo $_   
Desktop
$ cd ..     
$ echo $_
..

We can also use the variable in a script:

$ cat check_last_argument.sh
#!/bin/bash

echo "Initially, it holds the path to this script: $_"

# running another command
ls file1.txt 

echo "The value is now the last argument passed: $_"

Let’s now run the script:

$ bash check_last_argument.sh    
Initially, it holds the path to this script: /usr/bin/bash
file1.txt
The value is now the last argument passed: file1.txt

Notably, the behavior of $_ can be slightly unpredictable, especially in complex scripts or when dealing with multiple commands stringed together. Thus, it’s not recommended to rely solely on $_ for argument passing within scripts.

3. Shell Parameters

Beyond script-specific information, the shell environment offers valuable parameters that provide insight into its current state and execution flow. Let’s look at five crucial shell parameters.

3.1. The $- Variable

The $- parameter displays the currently set shell flags. These flags modify the shell’s behavior in various ways.

Understanding shell flags can be beneficial for advanced scripting or troubleshooting shell-related issues.

Let’s consider an example:

$ echo "Currently set shell flags: $-"  
Currently set shell flags: 3569JXZghikms

The output shows the currently enabled flags in the shell environment. The exact meaning of each flag might depend on the specific shell (Bash, Zsh, and so on).

We can also use the variable in a script to check for a specific flag:

$ cat check_flag.sh     
#!/bin/bash

echo "Currently set shell flags: $-"

if [[ "$-" == *h* ]]; then
  echo "The 'h' flag is set."
else
  echo "The 'h' flag is not set."
fi

Let’s run the script:

$ bash check_flag.sh
Currently set shell flags: hB
The 'h' flag is set.

The output shows us the set flags for the script and checks for a particular flag.

3.2. The $# Variable

The $# parameter expands to the number of arguments passed to the script when it’s executed.

It’s essential for handling arguments within the script. We can use it to check for the presence of arguments, to loop through them, or to access specific arguments by position which we’ll talk about later on.

Here’s how we can use the parameter in a script:

$ cat check_arguments.sh                     
#!/bin/bash

echo "Number of arguments passed: $#"

if [[ $# -eq 0 ]]; then
  echo "No arguments provided. Please provide a filename."
fi

The first echo statement displays the number of arguments, while the if statement provides an error message if there’s no argument.

Afterwards, we can run the script:

$ bash check_arguments.sh                    
Number of arguments passed: 0
No arguments provided. Please provide a filename.
$ bash check_arguments.sh file1.txt file2.txt  
Number of arguments passed: 2

We get an output telling us the number of arguments passed.

3.3. The $! Variable

The $! parameter holds the process ID (PID) of the most recently backgrounded command. Thus, it can be useful for monitoring or interacting with background processes in certain scripting scenarios.

Let’s start a background process:

$ sleep 10 &

We can then check the PID:

$ echo $!   
965283

This parameter also works in a script:

$ cat check_PID.sh      
#!/bin/bash

sleep 10 &

background_pid=$!
echo "Background process PID: $background_pid"

wait $background_pid
echo "Background process finished."

Next, let’s run the script:

$ bash check_PID.sh    
Background process PID: 806404
Background process finished.

Here, we capture the PID of the background process, and then we can see it displayed in the console.

3.4. The $$ Variable

The $$ parameter expands to the process ID of the current shell itself. While not commonly used in everyday scripting, it can be helpful for debugging. For instance, it can help in identifying the specific shell instance involved in an operation.

Let’s see it in practice:

$ echo $$ 
2661

We can also use it in a script:

$ cat check_script_PID.sh
#!/bin/bash

echo "This script's PID: $$"

Running this script will reveal its PID.

3.5. The $? Variable

$? holds the exit status of the most recently executed command.

Here’s how it works:

$ echo $?
0

A 0 exit status signifies successful execution while a non-zero exit status indicates an error or issue.

4. Positional Parameters

We often interact with shell scripts by passing arguments from the command line. These arguments are accessible within the script using a set of special dollar sign variables called positional parameters.

Furthermore, we can use them to interact with user-provided data and perform actions based on the arguments received.

4.1. The $n Variable

$n refers to the nth argument passed to the script, where n is an integer like 1, 2, 3, and so on. $1 represents the first argument, $2 represents the second argument, and $3 represents the third argument.

Let’s try it out in a script:

$ cat check_argument_number.sh
#!/bin/bash

echo "The first argument is: $1"
echo "The second argument is: $2"

We can then run the script with some arguments:

$ bash check_argument_number.sh file1.txt file2.txt
The first argument is: file1.txt
The second argument is: file2.txt

Subsequently, we can use this information to perform some other action conditionally.

4.2. The $@ Variable

This parameter is an array-like construct that holds all the arguments passed to the script.

Here’s an example of $@ in a script:

$ cat access_all_arguments.sh 
#!/bin/bash

echo "All arguments passed:"
for argument in "$@"
do
  echo "- $argument"
done

Let’s run the script with some arguments:

$ bash access_all_arguments.sh file1.txt file2.txt file3.txt
All arguments passed:
- file1.txt
- file2.txt
- file3.txt

With this parameter, we can iterate through arguments and process each one individually. Additionally, we can use it to seamlessly pass all received arguments to another command within the script.

4.3. The $* Variable

Similarly, $* represents all the arguments passed to the script. However, it differs slightly in how it handles arguments.

*Unlike $@, the $* parameter expands to a single string containing all arguments separated by a space*.

Let’s modify the script in the previous section:

$ cat access_all_arguments.sh
#!/bin/bash

echo "All arguments passed: "
echo "$*"

Now, let’s run the script again with the same arguments:

$ bash access_all_arguments.sh file1.txt file2.txt file3.txt
All arguments passed: 
file1.txt file2.txt file3.txt

This parameter is handy when we want to treat all the arguments as a single string.

5. Summary

So far, we’ve discussed various special dollar sign shell variables. Let’s summarize them all in a table:

Group

Variables

Description

Script Information

$0, $_

Give context about the script such as its name and last argument

Shell Parameters

$-, $#, $!, $$, $?

Information about the shell environment

Positional Parameters

$@, $*, $1, $2,

Arguments passed to the script

Notably, these variables aren’t restricted to the categories we’ve grouped them in. For instance, some shell parameters can be used within scripts as we saw earlier.

6. Conclusion

In this article, we’ve discussed various special dollar sign variables and their functionalities. We saw that these variables provide us access to script information, shell parameters, and user-provided arguments. This access enables us to automate tasks and interact with the system.