Command line arguments transform your bash scripts from static programs into flexible, reusable tools. Instead of hardcoding values or always prompting for input, you can make your scripts accept parameters directly when they're executed, just like professional command-line utilities.
๐ฏ What You'll Learn: In this comprehensive guide, you'll discover:
- How to access and use command line arguments in bash scripts
- The difference between
$1
,$2
,$@
, and$#
special variables - Proper argument validation and error handling techniques
- When to use
exit 1
vs continuing script execution - Building scripts that handle single and multiple parameters
- Best practices for user-friendly error messages
Time to read: ~9 minutes | Difficulty: Intermediate
๐ Understanding Command Line Arguments
Command line arguments are values you pass to a script when you run it. They make scripts flexible and allow users to provide different inputs without modifying the script itself.
Prerequisites
Before we dive in, make sure you have:
- Completed the Interactive Bash Scripts tutorial
- Understanding of bash variables and basic script structure
- Familiarity with loops (we'll cover the
for
loop in context)
๐ Your First Argument-Based Script
Let's start with a simple greeting script that accepts a name as a command line argument:
#!/bin/bash
if [ -z "$1" ]; then
echo "Usage: ./greet.sh <name>"
exit 1
fi
name=$1
echo "Hello $name!"
When you run this script:
# Without arguments - shows usage message
$ ./greet.sh
Usage: ./greet.sh <name>
# With argument - greets the user
$ ./greet.sh John
Hello John!
๐ Special Variables for Arguments
Bash provides several special variables to work with command line arguments:
| Variable | Description | Example |
|----------|-------------|---------|
| $0
| Script name | ./greet.sh
|
| $1
, $2
, $3
... | Individual arguments | John
, Bob
, Alice
|
| $@
| All arguments as separate strings | "John" "Bob" "Alice"
|
| $*
| All arguments as single string | "John Bob Alice"
|
| $#
| Number of arguments | 3
|
Accessing Individual Arguments
#!/bin/bash
echo "Script name: $0"
echo "First argument: $1"
echo "Second argument: $2"
echo "Third argument: $3"
echo "Number of arguments: $#"
echo "All arguments: $@"
Running this script:
$ ./argument-examples.sh Alice Bob Charlie
Script name: ./argument-examples.sh
First argument: Alice
Second argument: Bob
Third argument: Charlie
Number of arguments: 3
All arguments: Alice Bob Charlie
๐ก๏ธ Argument Validation Strategies
Single Argument Validation
Let's examine our greeting script's validation approach:
#!/bin/bash
# Method 1: Check if first argument is empty
if [ -z "$1" ]; then
echo "Usage: ./greet.sh <name>"
exit 1
fi
name=$1
echo "Hello $name!"
๐ก Understanding the Check: The -z "$1"
test returns true if the first argument is empty or doesn't exist. This is the most common way to validate required arguments.
Multiple Arguments Validation
For scripts that accept multiple arguments, we can check the argument count:
#!/bin/bash
# Method 2: Check argument count
if [ $# -eq 0 ]; then
echo "Usage: ./greet.sh <name1> <name2> ..."
exit 1
fi
# Process each argument
for name in "$@"; do
echo "Hello, $name!"
done
Testing with different argument counts:
# No arguments
$ ./greet.sh
Usage: ./greet.sh <name1> <name2> ...
# Single argument
$ ./greet.sh John
Hello, John!
# Multiple arguments
$ ./greet.sh John Bob Eve
Hello, John!
Hello, Bob!
Hello, Eve!
๐ฆ Exit Codes: When to Use exit 1
Understanding Exit Codes
Exit codes communicate script success or failure to the system and other programs:
โ Exit Code 0
- Meaning: Success
- When: Script completed normally
- Usage: Default exit (or explicit
exit 0
)
โ Exit Code 1 (or non-zero)
- Meaning: Error/Failure
- When: Invalid input, missing requirements
- Usage:
exit 1
(or other non-zero numbers)
Script with exit 1 (Recommended for Tools)
#!/bin/bash
if [ $# -eq 0 ]; then
echo "Error: No arguments supplied"
echo "Usage: ./greet.sh <name1> <name2> ..."
exit 1 # Stop execution and signal error
fi
for name in "$@"; do
echo "Hello, $name!"
done
# Implicit exit 0 (success)
Benefits of using exit 1:
- Other scripts can detect if your script failed
- Prevents further processing when requirements aren't met
- Professional behavior expected in command-line tools
- Enables proper error handling in automated systems
Script without exit (Alternative Approach)
#!/bin/bash
if [ $# -eq 0 ]; then
echo "Error: No arguments supplied"
echo "Usage: ./greet.sh <name1> <name2> ..."
echo "Using default greeting instead..."
echo "Hello, Guest!"
else
for name in "$@"; do
echo "Hello, $name!"
done
fi
When to avoid exit 1:
- Interactive scripts where you want to continue
- Scripts that can provide default behavior
- Educational or demonstration scripts
- When the "error" isn't truly critical
โ
Best Practice: Use exit 1
for validation errors in production scripts and command-line tools. It makes your scripts more reliable and professional.
๐ฏ Advanced Argument Handling
Handling Optional Arguments
#!/bin/bash
# Required argument
if [ -z "$1" ]; then
echo "Error: Username is required"
echo "Usage: $0 <username> [greeting] [punctuation]"
exit 1
fi
username=$1
greeting=${2:-"Hello"} # Default to "Hello" if not provided
punctuation=${3:-"!"} # Default to "!" if not provided
echo "$greeting $username$punctuation"
Testing optional arguments:
$ ./optional-arguments.sh Alice
Hello Alice!
$ ./optional-arguments.sh Bob "Good morning"
Good morning Bob!
$ ./optional-arguments.sh Charlie "Hey there" "."
Hey there Charlie.
Argument Count Validation
#!/bin/bash
# Require exactly 2 arguments
if [ $# -ne 2 ]; then
echo "Error: Expected exactly 2 arguments, got $#"
echo "Usage: $0 <first_name> <last_name>"
exit 1
fi
first_name=$1
last_name=$2
echo "Full name: $first_name $last_name"
Range-Based Validation
#!/bin/bash
# Require between 1 and 5 arguments
if [ $# -lt 1 ] || [ $# -gt 5 ]; then
echo "Error: Expected 1-5 arguments, got $#"
echo "Usage: $0 <name1> [name2] [name3] [name4] [name5]"
exit 1
fi
echo "Greeting $# people:"
for name in "$@"; do
echo "Hello, $name!"
done
๐ ๏ธ Real-World Examples
Example 1: File Backup Script
#!/bin/bash
# Validate arguments
if [ $# -lt 2 ]; then
echo "Error: Insufficient arguments"
echo "Usage: $0 <source_file1> [source_file2] ... <destination_directory>"
echo "Example: $0 file1.txt file2.txt /backup/"
exit 1
fi
# Get destination (last argument)
destination="${!#}"
# Check if destination exists and is a directory
if [ ! -d "$destination" ]; then
echo "Error: Destination '$destination' is not a valid directory"
exit 1
fi
# Process all files except the last argument (destination)
file_count=0
for ((i=1; i<$#; i++)); do
source_file="${!i}"
if [ -f "$source_file" ]; then
cp "$source_file" "$destination"
echo "Backed up: $source_file -> $destination"
file_count=$((file_count + 1))
else
echo "Warning: File '$source_file' not found, skipping..."
fi
done
echo "Backup completed. $file_count files copied to $destination"
Example 2: System Information Script
#!/bin/bash
# Default to showing all info if no arguments
if [ $# -eq 0 ]; then
echo "Showing all system information..."
show_all=true
else
show_all=false
fi
show_system_info() {
echo "=== System Information ==="
uname -a
echo ""
}
show_memory_info() {
echo "=== Memory Information ==="
free -h
echo ""
}
show_disk_info() {
echo "=== Disk Information ==="
df -h
echo ""
}
# Process arguments or show all
if [ "$show_all" = true ]; then
show_system_info
show_memory_info
show_disk_info
else
for arg in "$@"; do
case $arg in
system|sys)
show_system_info
;;
memory|mem)
show_memory_info
;;
disk|storage)
show_disk_info
;;
*)
echo "Warning: Unknown option '$arg'"
echo "Valid options: system, memory, disk"
;;
esac
done
fi
Usage examples:
$ ./sysinfo.sh # Show all information
$ ./sysinfo.sh system memory # Show only system and memory info
$ ./sysinfo.sh disk # Show only disk information
๐จ Professional Error Messages
Clear Usage Instructions
#!/bin/bash
show_usage() {
echo "Usage: $(basename $0) [OPTIONS] <command> [arguments...]"
echo ""
echo "Commands:"
echo " create <name> Create a new item"
echo " delete <name> Delete an item"
echo " list List all items"
echo ""
echo "Options:"
echo " -h, --help Show this help message"
echo " -v, --verbose Enable verbose output"
echo ""
echo "Examples:"
echo " $0 create my-item"
echo " $0 delete old-item"
echo " $0 --verbose list"
}
# Check for help flags
case "$1" in
-h|--help)
show_usage
exit 0
;;
esac
# Validate minimum arguments
if [ $# -eq 0 ]; then
echo "Error: No command specified"
echo ""
show_usage
exit 1
fi
# Rest of script logic...
Descriptive Error Messages
#!/bin/bash
validate_email() {
local email=$1
if [[ ! $email =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$ ]]; then
return 1
fi
return 0
}
if [ $# -ne 2 ]; then
echo "Error: Invalid number of arguments"
echo "Expected: 2 arguments (name and email)"
echo "Received: $# arguments"
echo ""
echo "Usage: $0 <full_name> <email_address>"
echo "Example: $0 'John Doe' 'john@example.com'"
exit 1
fi
name="$1"
email="$2"
# Validate name
if [ ${#name} -lt 2 ]; then
echo "Error: Name too short"
echo "Name must be at least 2 characters long"
echo "Provided: '$name' (${#name} characters)"
exit 1
fi
# Validate email
if ! validate_email "$email"; then
echo "Error: Invalid email format"
echo "Provided: '$email'"
echo "Expected format: user@domain.com"
exit 1
fi
echo "Valid input received:"
echo "Name: $name"
echo "Email: $email"
๐งช Testing Your Scripts
Testing Different Scenarios
#!/bin/bash
script_to_test="./greet.sh"
echo "=== Testing Argument Handling ==="
echo ""
echo "Test 1: No arguments"
$script_to_test
echo "Exit code: $?"
echo ""
echo "Test 2: Single argument"
$script_to_test "Alice"
echo "Exit code: $?"
echo ""
echo "Test 3: Multiple arguments"
$script_to_test "John" "Bob" "Eve"
echo "Exit code: $?"
echo ""
echo "Test 4: Argument with spaces"
$script_to_test "John Doe"
echo "Exit code: $?"
echo ""
๐ก Testing Tip: The $?
variable contains the exit code of the last executed command. Use it to verify your error handling works correctly.
๐ฏ Key Takeaways
โ Remember These Points
- Always Validate Arguments: Check for required parameters before processing
- Use Clear Error Messages: Help users understand what went wrong and how to fix it
- Exit with Proper Codes: Use
exit 1
for errors,exit 0
(or no exit) for success - Quote Variables: Always use
"$@"
and"$1"
to handle arguments with spaces - Provide Usage Instructions: Show users how to use your script when they make mistakes
๐ Further Reading
Official Resources
๐ Fantastic Progress! You now understand how to build flexible bash scripts that accept command line arguments, validate input properly, and handle errors gracefully. This is a major step toward creating professional command-line tools.
๐ฌ Discussion
I'd love to hear about your command-line scripting projects:
- What's the most useful parameterized script you've created or want to create?
- How do you prefer to handle optional vs required arguments?
- Have you encountered any tricky argument parsing scenarios?
- What command-line tools inspire your scripting approach?
Connect with me:
- ๐ GitHub - Command-line script examples and templates
- ๐ง Contact - Advanced scripting questions and discussions