Positional Parameters in Shell Script
Last Updated :
17 Nov, 2025
Positional parameters are a set of special variables in shell scripting (like $1, $2, $#) that hold the arguments passed to your script from the command line.
- Using them is the key to creating powerful, flexible tools.
- Instead of a script that can only back up one specific file, you can create a script that can back up any file you "pass" to it.
You will use positional parameters to:
- Make your scripts reusable and non-static.
- Get required information, like a filename, a host to ping, or a directory.
- Make your scripts behave like real Linux commands (e.g., cp [source] [destination]).
A Simple Greeting Script
#!/bin/bash
# $1 will be the first argument
# $2 will be the second argument
echo "Hello, $1!"
echo "Welcome to $2."
Output:
The Special Variables
When your script runs, the shell automatically populates these special variables.
- $1, $2, $3...$9: The first nine positional parameters.
- ${10}, ${11}...: To access arguments beyond the 9th, you must use curly braces.
- $0: The name of the script itself. This is great for error messages.
- $#: The total number (count) of arguments provided. This is your most important tool for error checking.
- $*: All arguments as a single string.
- $@: All arguments as a list of separate strings.
The Most Important Concept: "$@" Vs "$*"
This is the most critical and confusing part of positional parameters. The difference is how they behave when quoted.
Let's say you run ./myscript.sh "My File.txt" "Other File.txt".
| Variable | How it Behaves | Resulting Strings |
| $* | Expands to My File.txt Other File.txt | My, File.txt, Other, File.txt (4 strings) |
| $@ | Expands to My File.txt Other File.txt | My, File.txt, Other, File.txt (4 strings) |
| "$*" | Expands to "My File.txt Other File.txt" | "My File.txt Other File.txt" (1 string) |
| "$@" | Expands to "My File.txt" "Other File.txt" | "My File.txt", "Other File.txt" (2 strings) |
Important:
- To loop through arguments and preserve spaces in filenames, always use for arg in "$@".
- To print all arguments in one go, you might use echo "$*.
Looping Through All Arguments ($@)
This is the main use for "$@". You can create a script that processes an unlimited number of arguments.
Here is a ping_hosts.sh script that pings every host you give it.
#!/bin/bash
# If no hosts are given, show an error
if [ "$#" -eq 0 ]; then
echo "Error: No hosts provided."
echo "Usage: $0 [host1] [host2] ..."
exit 1
fi
echo "Pinging all hosts..."
# This loop will run once for each argument
# Using "$@" ensures that filenames with spaces are treated as one item
for host in "$@"
do
echo "--- Pinging $host ---"
ping -c 3 "$host"
echo "---------------------"
done
echo "All pings complete."
Running it:
./ping_hosts.sh google.com 8.8.8.8
Processing Arguments with shift
The shift command is an advanced tool. It "shifts" all arguments one to the left:
- $2 becomes $1
- $3 becomes $2
- The original $1 is discarded.
- $# is decreased by one.
This is useful for processing arguments one by one in a while loop.
#!/bin/bash
# Loop as long as the number of arguments (-gt) is "greater than" 0
while [ "$#" -gt 0 ]
do
echo "Processing argument: $1"
echo "Arguments left: $#"
# Discard $1 and move $2 into its place
shift
echo "---"
done
echo "All arguments processed."
Running it :
./shift_test.sh apple banana cherry
Output:
Positional Parameters Options:
| Variable | What It Is |
|---|
| $0 | The name of the script itself. |
| $1 | The 1st argument. |
| $9 | The 9th argument. |
| ${10} | The 10th argument (braces are required). |
| $# | The total number (count) of arguments. |
| "$@" | All arguments as a list of separate, quoted strings. (Use this in loops!) |
| "$*" | All arguments as a single, quoted string. |
| $? | The exit status of the last command (0 for success). |
Explore
Linux/Unix Tutorial
5 min read
Getting Started with Linux
Installation with Linux
Linux Commands
Linux File System
Linux Kernel
Linux Networking Tools
Linux Process
Linux Firewall
Shell Scripting & Bash Scripting