Special Variables in Shell

ShellShellBeginner
Practice Now

Introduction

In this lab, you will learn about special variables in shell scripting. These variables provide essential information about the script execution environment, such as command-line arguments, script name, and process ID. Understanding these variables will help you write more flexible and powerful shell scripts.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL shell(("`Shell`")) -.-> shell/ControlFlowGroup(["`Control Flow`"]) linux(("`Linux`")) -.-> linux/BasicSystemCommandsGroup(["`Basic System Commands`"]) linux(("`Linux`")) -.-> linux/BasicFileOperationsGroup(["`Basic File Operations`"]) shell(("`Shell`")) -.-> shell/BasicSyntaxandStructureGroup(["`Basic Syntax and Structure`"]) shell(("`Shell`")) -.-> shell/VariableHandlingGroup(["`Variable Handling`"]) shell(("`Shell`")) -.-> shell/FunctionsandScopeGroup(["`Functions and Scope`"]) shell/ControlFlowGroup -.-> shell/if_else("`If-Else Statements`") linux/BasicSystemCommandsGroup -.-> linux/echo("`Text Display`") linux/BasicFileOperationsGroup -.-> linux/touch("`File Creating/Updating`") linux/BasicFileOperationsGroup -.-> linux/chmod("`Permission Modifying`") shell/BasicSyntaxandStructureGroup -.-> shell/shebang("`Shebang`") shell/BasicSyntaxandStructureGroup -.-> shell/comments("`Comments`") shell/VariableHandlingGroup -.-> shell/variables_usage("`Variable Usage`") shell/ControlFlowGroup -.-> shell/for_loops("`For Loops`") shell/FunctionsandScopeGroup -.-> shell/func_def("`Function Definition`") subgraph Lab Skills shell/if_else -.-> lab-388819{{"`Special Variables in Shell`"}} linux/echo -.-> lab-388819{{"`Special Variables in Shell`"}} linux/touch -.-> lab-388819{{"`Special Variables in Shell`"}} linux/chmod -.-> lab-388819{{"`Special Variables in Shell`"}} shell/shebang -.-> lab-388819{{"`Special Variables in Shell`"}} shell/comments -.-> lab-388819{{"`Special Variables in Shell`"}} shell/variables_usage -.-> lab-388819{{"`Special Variables in Shell`"}} shell/for_loops -.-> lab-388819{{"`Special Variables in Shell`"}} shell/func_def -.-> lab-388819{{"`Special Variables in Shell`"}} end

Creating Your First Script

Let's start by creating a simple shell script to demonstrate the use of special variables.

  1. Open your terminal in the WebIDE. You should see a command prompt waiting for your input.

  2. Navigate to the project directory:

cd ~/project

This command changes your current directory to ~/project, which is your default working directory for this lab.

  1. Create a new file named special_vars.sh using the following command:
touch special_vars.sh

The touch command creates an empty file if it doesn't exist, or updates its timestamp if it does.

  1. Open the file in the WebIDE editor. You can do this by clicking on the file name in the file explorer on the left side of your screen.

  2. Add the following content to the file:

#!/bin/bash

echo "Script Name: $0"
echo "First Argument: $1"
echo "Second Argument: $2"
echo "All Arguments: $@"
echo "Number of Arguments: $#"
echo "Process ID: $$"

Let's break down what each line does:

  • #!/bin/bash: This is called a shebang. It tells the system to use bash to interpret this script.
  • $0: This special variable holds the name of the script.
  • $1 and $2: These represent the first and second command-line arguments respectively.
  • $@: This represents all the command-line arguments passed to the script.
  • $#: This gives the count of command-line arguments.
  • $$: This provides the process ID of the current shell.
  1. Save the file after adding the content.

  2. Make the script executable by running the following command in your terminal:

chmod +x special_vars.sh

The chmod command changes the permissions of a file. The +x option adds execute permission, allowing you to run the script.

Running the Script with Arguments

Now that we have created our script, let's run it with different arguments to see how the special variables behave.

  1. Run the script without any arguments:
./special_vars.sh

The ./ before the script name tells the shell to look for the script in the current directory.

You should see output similar to this:

Script Name: ./special_vars.sh
First Argument:
Second Argument:
All Arguments:
Number of Arguments: 0
Process ID: 1234

Notice that the first and second arguments are empty, and the number of arguments is 0 since we didn't provide any.

  1. Now, run the script with some arguments:
./special_vars.sh hello world

The output should look like this:

Script Name: ./special_vars.sh
First Argument: hello
Second Argument: world
All Arguments: hello world
Number of Arguments: 2
Process ID: 1235

Here's what changed:

  • $1 now contains "hello"
  • $2 now contains "world"
  • $@ shows all arguments: "hello world"
  • $# shows 2, because we provided two arguments

The Process ID ($$) might be different each time you run the script, as it's assigned by the operating system.

Understanding $? and $

Two other important special variables are $? and $!. Let's create a new script to demonstrate their use.

  1. Create a new file named exit_status.sh:
touch ~/project/exit_status.sh
  1. Open the file in the WebIDE editor and add the following content:
#!/bin/bash

echo "Running a successful command:"
ls /home
echo "Exit status: $?"

echo "Running a command that will fail:"
ls /nonexistent_directory
echo "Exit status: $?"

echo "Running a background process:"
sleep 2 &
echo "Process ID of last background command: $!"

Let's break down this script:

  • $? gives the exit status of the last executed command. 0 typically means success, while non-zero values indicate various error conditions.
  • $! gives the process ID of the last background command.
  • The & at the end of a command runs it in the background.
  1. Save the file and make it executable:
chmod +x ~/project/exit_status.sh
  1. Run the script:
./exit_status.sh

You should see output similar to this:

Running a successful command:
labex
Exit status: 0
Running a command that will fail:
ls: cannot access '/nonexistent_directory': No such file or directory
Exit status: 2
Running a background process:
Process ID of last background command: 1236

Notice:

  • The first ls command succeeds, so $? is 0.
  • The second ls command fails (because the directory doesn't exist), so $? is 2 (a non-zero value indicating an error).
  • The sleep command runs in the background, and $! gives its process ID.

Using Special Variables in Functions

Special variables can also be used within functions. Let's create a script to demonstrate this.

  1. Create a new file named function_vars.sh:
touch ~/project/function_vars.sh
  1. Open the file in the WebIDE editor and add the following content:
#!/bin/bash

function print_args {
  echo "Function Name: $0"
  echo "First Argument: $1"
  echo "Second Argument: $2"
  echo "All Arguments: $@"
  echo "Number of Arguments: $#"
}

echo "Calling function with two arguments:"
print_args hello world

echo "Calling function with four arguments:"
print_args one two three four

This script defines a function print_args that uses special variables. Then it calls this function twice with different numbers of arguments.

  1. Save the file and make it executable:
chmod +x ~/project/function_vars.sh
  1. Run the script:
./function_vars.sh

You should see output similar to this:

Calling function with two arguments:
Function Name: ./function_vars.sh
First Argument: hello
Second Argument: world
All Arguments: hello world
Number of Arguments: 2
Calling function with four arguments:
Function Name: ./function_vars.sh
First Argument: one
Second Argument: two
All Arguments: one two three four
Number of Arguments: 4

Notice that:

  • $0 still refers to the script name, not the function name.
  • $1, $2, $@, and $# work for function arguments just like they do for script arguments.
  • The values of these variables change each time the function is called with different arguments.

Understanding the Difference Between $@ and $*

The special variables $@ and $* are both used to represent all command-line arguments, but they behave differently when enclosed in double quotes. Let's create a script to demonstrate this difference.

  1. Create a new file named at_vs_star.sh:
touch ~/project/at_vs_star.sh
  1. Open the file in the WebIDE editor and add the following content:
#!/bin/bash

echo "Using \$@:"
for arg in "$@"; do
  echo "Argument: $arg"
done

echo "Using \$*:"
for arg in "$*"; do
  echo "Argument: $arg"
done

This script demonstrates the difference between $@ and $* when used in a loop.

  1. Save the file and make it executable:
chmod +x ~/project/at_vs_star.sh
  1. Run the script with multiple arguments, including some with spaces:
./at_vs_star.sh "arg with spaces" another_arg "third arg"

You should see output similar to this:

Using $@:
Argument: arg with spaces
Argument: another_arg
Argument: third arg
Using $*:
Argument: arg with spaces another_arg third arg

Here's what's happening:

  • With "$@", each argument is treated as a separate entity. Arguments with spaces are preserved as single units.
  • With "$*", all arguments are combined into a single string, separated by the first character of the IFS (Internal Field Separator) variable, which is usually a space.

This difference is crucial when you need to process arguments that might contain spaces or other special characters.

Summary

In this lab, you have learned about special variables in shell scripting and how to use them effectively. You have created scripts that demonstrate the usage of various special variables such as $0, $1, $@, $#, $$, $?, and $!. You have also explored how these variables behave in different contexts, including within functions and when handling command-line arguments.

Key takeaways:

  1. $0, $1, $2, etc. represent the script name and command-line arguments.
  2. $@ and $# allow you to work with all arguments and count them.
  3. $$ gives you the current process ID, useful for creating unique temporary files.
  4. $? helps you check if the previous command was successful.
  5. $! gives you the PID of the last background process, useful for job control.
  6. $@ and $* behave differently when quoted, which is important when handling arguments with spaces.

Understanding these special variables is crucial for writing more advanced and flexible shell scripts. They allow you to create scripts that can adapt to different inputs and provide valuable information about the script's execution environment.

As you continue to practice and experiment with shell scripting, you'll find many more ways to leverage these special variables in your work. Remember to consult the bash manual (man bash) for more detailed information on these and other special variables.

Other Shell Tutorials you may like