Bash Positional Parameters

Positional parameters are Bash variables that store the arguments given to a script or function. They help you to write flexible and convenient scripts that can accept input from the command line.
Understanding positional parameters is essential for writing useful Bash scripts. In this guide, you will learn how to access and work with command-line arguments in your scripts. If you’re new to the command line, start with our guide on basic Linux commands .
What Are Positional Parameters?
S When you run a script with arguments, Bash assigns each argument to a numbered variable called a positional parameter:
./script.sh arg1 arg2 arg3In this example:
$0contains the script name (./script.sh)$1contains the first argument (arg1)$2contains the second argument (arg2)$3contains the third argument (arg3)
Accessing Positional Parameters
Basic Parameters ($1, $2, $3, …)
The most common way to access arguments is through $1, $2, $3, and so on:
#!/bin/bash
echo "Hello, $1!"
echo "You are from $2."Run the script:
./greet.sh Leah SeattleHello, Leah!
You are from Seattle.Parameters Beyond $9
For parameters beyond $9, use curly braces:
echo "The tenth argument is: ${10}"
echo "The eleventh argument is: ${11}"If you don’t use braces, $10 would be interpreted as $1 followed by a literal 0.
Special Parameter Variables
Bash provides several special variables for working with positional parameters:
| Variable | Description |
|---|---|
$0 | The name of the script |
$1 - $9 | The first 9 arguments |
${10} … | Arguments 10 and beyond |
$# | The number of arguments |
$@ | All arguments as separate words |
$* | All arguments as a single word |
The Script Name ($0)
The $0 variable contains the name of the script as it was called:
#!/bin/bash
echo "This script is called: $0"./showname.shThis script is called: ./showname.shCounting Arguments ($#)
The $# variable holds the number of arguments passed to the script:
#!/bin/bash
echo "You provided $# arguments."./count.sh one two threeYou provided 3 arguments.This is helpful when you want to check if the right number of arguments was given:
#!/bin/bash
if [ $# -lt 2 ]; then
echo "Usage: $0 <source> <destination>"
exit 1
fi
echo "Copying from $1 to $2"All Arguments ($@ and $*)
Both $@ and $* represent all arguments, but they behave differently when quoted.
Without quotes, they are identical:
for arg in $@; do echo "$arg"; done
for arg in $*; do echo "$arg"; doneBut, With quotes, they behave differently:
"$@"expands to"$1" "$2" "$3"(separate strings)"$*"expands to"$1 $2 $3"(single string)
#!/bin/bash
echo "Using \"\$@\":"
for arg in "$@"; do
echo " - $arg"
done
echo ""
echo "Using \"\$*\":"
for arg in "$*"; do
echo " - $arg"
done./compare.sh "hello world" foo barUsing "$@":
- hello world
- foo bar
Using "$*":
- hello world foo barNotice that "$@" preserved “hello world” as a single argument, while "$*" joined everything into one string.
Best practice: Use "$@" when you need to pass arguments to another command or iterate over them individually.
The shift Command
The shift built-in command removes the first positional parameter and shifts all others down by one:
$2becomes$1$3becomes$2- And so on…
#!/bin/bash
echo "Before shift:"
echo " \$1 = $1"
echo " \$2 = $2"
echo " \$3 = $3"
shift
echo ""
echo "After shift:"
echo " \$1 = $1"
echo " \$2 = $2"
echo " \$3 = $3"./shift_example.sh apple banana cherryBefore shift:
$1 = apple
$2 = banana
$3 = cherry
After shift:
$1 = banana
$2 = cherry
$3 =Shifting Multiple Positions
You can also use shift to move the positional parameters by more than one position at a time:
shift 3 # Shifts by 3 positionsProcessing All Arguments with shift
The shift command is useful for processing arguments one at a time:
#!/bin/bash
while [ $# -gt 0 ]; do
echo "Processing: $1"
shift
done
echo "Done. All arguments processed."./process_all.sh file1.txt file2.txt file3.txtProcessing: file1.txt
Processing: file2.txt
Processing: file3.txt
Done. All arguments processed.Practical Examples
Example 1: File Backup Script
Here’s a script that backs up a file to a directory you choose:
#!/bin/bash
# Check for required arguments
if [ $# -ne 2 ]; then
echo "Usage: $0 <file> <backup_dir>"
exit 1
fi
SOURCE="$1"
BACKUP_DIR="$2"
# Check if the source file exists
if [ ! -f "$SOURCE" ]; then
echo "Error: File '$SOURCE' not found."
exit 1
fi
# Create a backup directory if it doesn't exist
mkdir -p "$BACKUP_DIR"
# Create backup with timestamp
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
FILENAME=$(basename "$SOURCE")
cp "$SOURCE" "$BACKUP_DIR/${FILENAME}.${TIMESTAMP}.bak"
echo "Backup created: $BACKUP_DIR/${FILENAME}.${TIMESTAMP}.bak"Example 2: Simple Calculator
This script does simple arithmetic calculations:
#!/bin/bash
if [ $# -ne 3 ]; then
echo "Usage: $0 <number1> <operator> <number2>"
echo "Operators: + - x /"
exit 1
fi
NUM1=$1
OP=$2
NUM2=$3
case $OP in
+) RESULT=$((NUM1 + NUM2)) ;;
-) RESULT=$((NUM1 - NUM2)) ;;
x) RESULT=$((NUM1 * NUM2)) ;;
/) RESULT=$((NUM1 / NUM2)) ;;
*) echo "Unknown operator: $OP"; exit 1 ;;
esac
echo "$NUM1 $OP $NUM2 = $RESULT"./calc.sh 10 + 5
./calc.sh 20 x 310 + 5 = 15
20 x 3 = 60Example 3: Processing Command-Line Options
This script shows how to handle flags and arguments:
#!/bin/bash
VERBOSE=false
OUTPUT=""
while [ $# -gt 0 ]; do
case $1 in
-v|--verbose)
VERBOSE=true
shift
;;
-o|--output)
OUTPUT="$2"
shift 2
;;
-h|--help)
echo "Usage: $0 [-v] [-o output_file] [files...]"
exit 0
;;
-*)
echo "Unknown option: $1"
exit 1
;;
*)
break
;;
esac
done
# The remaining arguments are files
if [ "$VERBOSE" = true ]; then
echo "Verbose mode enabled"
echo "Output file: ${OUTPUT:-stdout}"
echo "Files to process: $@"
fi
for file in "$@"; do
echo "Processing: $file"
donePositional Parameters in Functions
You can use positional parameters inside functions, too. Each function gets its own set of these parameters:
#!/bin/bash
greet() {
echo "Hello, $1! You are $2 years old."
}
# Script arguments
echo "Script name: $0"
echo "Script argument 1: $1"
# Function arguments (separate from script arguments)
greet "Zoe" 30
greet "Luca" 25./func_params.sh test_argScript name: ./func_params.sh
Script argument 1: test_arg
Hello, Zoe! You are 30 years old.
Hello, Luca! You are 25 years old.Default Values for Parameters
You can set default values for parameters if they aren’t provided:
#!/bin/bash
NAME="${1:-Guest}"
GREETING="${2:-Hello}"
echo "$GREETING, $NAME!"./defaults.sh
./defaults.sh Leah
./defaults.sh Leah "Good morning"Hello, Guest!
Hello, Leah!
Good morning, Leah!The syntax ${VAR:-default} returns default if VAR is unset or empty.
Conclusion
Positional parameters are fundamental to writing flexible Bash scripts that accept command-line arguments. Here are the main things to remember:
- Positional parameters
$1,$2,$3…$n, correspond to the position of the parameter after the script’s name. - The
$0variable is reserved for the script’s name. $#gives you the argument count."$@"is the best way to pass all arguments to another command.shiftlets you process arguments one at a time.- Always validate the number of arguments before using them.
Knowing how to use positional parameters allows you to create Bash scripts that are both powerful and user-friendly. For more details on executing scripts, see our guide on how to run a bash script .
If you have any questions or feedback, please leave a comment.
Tags
Linuxize Weekly Newsletter
A quick weekly roundup of new tutorials, news, and tips.
About the authors

Dejan Panovski
Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.
View author page