Shell Script Arguments: Complete Guide with Examples

Master shell script arguments with this comprehensive guide covering positional parameters, special variables, and advanced techniques.

Shell Script Arguments: Complete Guide

Overview

Shell script arguments are command-line parameters passed to a script when it is executed. These arguments allow scripts to be flexible and reusable by accepting input data from the user or other programs. Arguments are essential for creating dynamic scripts that can process different data sets or perform various operations based on user input.

Table of Contents

1. [Basic Concepts](#basic-concepts) 2. [Positional Parameters](#positional-parameters) 3. [Special Variables](#special-variables) 4. [Argument Processing Techniques](#argument-processing-techniques) 5. [Advanced Argument Handling](#advanced-argument-handling) 6. [Error Handling](#error-handling) 7. [Best Practices](#best-practices) 8. [Examples and Use Cases](#examples-and-use-cases)

Basic Concepts

When a shell script is executed, any additional words on the command line become arguments to the script. These arguments are automatically assigned to special variables that can be accessed within the script.

Syntax

`bash ./script_name.sh argument1 argument2 argument3 ... `

The shell automatically parses the command line and assigns each space-separated word to numbered variables starting from $1.

Positional Parameters

Positional parameters are the primary mechanism for accessing command-line arguments in shell scripts. They are referenced using the dollar sign followed by a number.

Basic Positional Parameters

| Parameter | Description | |-----------|-------------| | $0 | The name of the script itself | | $1 | The first argument | | $2 | The second argument | | $3 | The third argument | | $n | The nth argument (where n > 9, use ${n}) |

Example Script: basic_args.sh

`bash #!/bin/bash

Basic argument demonstration

echo "Script name: $0" echo "First argument: $1" echo "Second argument: $2" echo "Third argument: $3" `

Execution: `bash chmod +x basic_args.sh ./basic_args.sh hello world 123 `

Output: ` Script name: ./basic_args.sh First argument: hello Second argument: world Third argument: 123 `

Accessing Arguments Beyond $9

For arguments beyond the ninth position, use curly braces:

`bash #!/bin/bash

echo "Tenth argument: ${10}" echo "Eleventh argument: ${11}" `

Special Variables

Shell scripts provide several special variables for working with arguments:

Complete Special Variables Table

| Variable | Description | Example Usage | |----------|-------------|---------------| | $# | Number of arguments passed | if [ $# -eq 0 ]; then echo "No arguments"; fi | | $@ | All arguments as separate words | for arg in "$@"; do echo $arg; done | | $ | All arguments as a single word | echo "All args: $" | | $ | Process ID of current script | echo "PID: $" | | $? | Exit status of last command | command; if [ $? -eq 0 ]; then echo "Success"; fi | | $! | Process ID of last background command | command &; echo "Background PID: $!" |

Detailed Explanation of $@ vs $*

The difference between $@ and $* becomes important when dealing with quoted arguments:

`bash #!/bin/bash

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

echo "Using \$*:" for arg in "$*"; do echo " [$arg]" done `

Execution: `bash ./script.sh "hello world" "foo bar" `

Output: ` Using $@: [hello world] [foo bar] Using $*: [hello world foo bar] `

Argument Processing Techniques

Basic Validation

Always validate the number and type of arguments:

`bash #!/bin/bash

Check if correct number of arguments provided

if [ $# -ne 2 ]; then echo "Usage: $0 " exit 1 fi

source_file="$1" dest_file="$2"

Check if source file exists

if [ ! -f "$source_file" ]; then echo "Error: Source file '$source_file' does not exist" exit 1 fi

echo "Copying $source_file to $dest_file" cp "$source_file" "$dest_file" `

Processing All Arguments

`bash #!/bin/bash

echo "Processing $# arguments:"

Method 1: Using $@

for arg in "$@"; do echo "Processing: $arg" done

Method 2: Using while loop and shift

while [ $# -gt 0 ]; do echo "Current argument: $1" shift # Move to next argument done `

The shift Command

The shift command moves positional parameters to the left:

| Command | Effect | |---------|--------| | shift | $2 becomes $1, $3 becomes $2, etc. | | shift 2 | Shifts by 2 positions | | shift n | Shifts by n positions |

`bash #!/bin/bash

echo "Before shift: $1 $2 $3" shift echo "After shift: $1 $2 $3" shift 2 echo "After shift 2: $1 $2 $3" `

Advanced Argument Handling

Option Processing with getopts

The getopts command provides a standardized way to process command-line options:

`bash #!/bin/bash

Default values

verbose=false output_file="" input_file=""

Process options

while getopts "vo:i:h" opt; do case $opt in v) verbose=true ;; o) output_file="$OPTARG" ;; i) input_file="$OPTARG" ;; h) echo "Usage: $0 [-v] [-o output_file] [-i input_file]" echo " -v: Verbose mode" echo " -o: Output file" echo " -i: Input file" echo " -h: Show this help" exit 0 ;; \?) echo "Invalid option: -$OPTARG" >&2 exit 1 ;; :) echo "Option -$OPTARG requires an argument." >&2 exit 1 ;; esac done

Shift past processed options

shift $((OPTIND-1))

Remaining arguments are in $@

echo "Verbose: $verbose" echo "Output file: $output_file" echo "Input file: $input_file" echo "Remaining arguments: $@" `

getopts Variables and Options

| Variable | Description | |----------|-------------| | OPTARG | Contains the argument for options that require one | | OPTIND | Index of the next argument to process | | opt | Current option being processed |

| Option String | Meaning | |---------------|---------| | "abc" | Options -a, -b, -c (no arguments) | | "a:b:c" | Option -a and -b require arguments, -c doesn't | | ":abc" | Silent mode (custom error handling) |

Long Options Processing

For long options (--option), you need custom processing:

`bash #!/bin/bash

while [[ $# -gt 0 ]]; do case $1 in --verbose|-v) verbose=true shift ;; --output|-o) output_file="$2" shift 2 ;; --input|-i) input_file="$2" shift 2 ;; --help|-h) echo "Usage: $0 [OPTIONS]" echo "Options:" echo " --verbose, -v Enable verbose mode" echo " --output, -o Specify output file" echo " --input, -i Specify input file" echo " --help, -h Show this help" exit 0 ;; -*) echo "Unknown option: $1" >&2 exit 1 ;; *) # Positional argument positional_args+=("$1") shift ;; esac done `

Error Handling

Comprehensive Error Checking

`bash #!/bin/bash

Function to display usage

usage() { echo "Usage: $0 [file2...]" echo "Commands: copy, move, delete" exit 1 }

Function to check if file exists

check_file() { if [ ! -f "$1" ]; then echo "Error: File '$1' does not exist" >&2 exit 1 fi }

Check minimum arguments

if [ $# -lt 2 ]; then echo "Error: Insufficient arguments" >&2 usage fi

command="$1" shift

Validate command

case "$command" in copy|move|delete) ;; *) echo "Error: Invalid command '$command'" >&2 usage ;; esac

Process files

for file in "$@"; do check_file "$file" echo "Processing $file with command $command" done `

Exit Codes Table

| Exit Code | Meaning | |-----------|---------| | 0 | Success | | 1 | General error | | 2 | Misuse of shell command | | 126 | Command invoked cannot execute | | 127 | Command not found | | 128+n | Fatal error signal "n" |

Best Practices

Input Validation and Security

`bash #!/bin/bash

Always quote variables to handle spaces

safe_copy() { local source="$1" local dest="$2" # Validate input if [ -z "$source" ] || [ -z "$dest" ]; then echo "Error: Both source and destination required" >&2 return 1 fi # Check for dangerous characters if [[ "$dest" =~ [;&|] ]]; then echo "Error: Invalid characters in destination" >&2 return 1 fi cp "$source" "$dest" }

Use arrays for multiple arguments

declare -a files while [[ $# -gt 0 ]]; do files+=("$1") shift done

Process array

for file in "${files[@]}"; do echo "Processing: $file" done `

Documentation and Help

`bash #!/bin/bash

Script: file_processor.sh

Description: Process files with various operations

Author: Your Name

Version: 1.0

show_help() { cat << EOF NAME file_processor.sh - Process files with various operations

SYNOPSIS $0 [OPTIONS] COMMAND FILE...

DESCRIPTION This script processes files with the specified command.

OPTIONS -v, --verbose Enable verbose output -h, --help Show this help message -o, --output DIR Specify output directory

COMMANDS copy Copy files to output directory move Move files to output directory list List file information

EXAMPLES $0 copy file1.txt file2.txt $0 -v --output /tmp move *.log $0 list document.pdf

EXIT STATUS 0 Success 1 General error 2 Invalid arguments

EOF } `

Examples and Use Cases

Example 1: File Backup Script

`bash #!/bin/bash

backup.sh - Create backups of specified files

backup_dir="/backup" timestamp=$(date +%Y%m%d_%H%M%S) verbose=false

Process options

while getopts "d:vh" opt; do case $opt in d) backup_dir="$OPTARG" ;; v) verbose=true ;; h) echo "Usage: $0 [-d backup_dir] [-v] file1 [file2...]" exit 0 ;; esac done shift $((OPTIND-1))

Check arguments

if [ $# -eq 0 ]; then echo "Error: No files specified" >&2 exit 1 fi

Create backup directory

mkdir -p "$backup_dir" || { echo "Error: Cannot create backup directory" >&2 exit 1 }

Backup files

for file in "$@"; do if [ -f "$file" ]; then backup_name="${backup_dir}/$(basename "$file").${timestamp}" cp "$file" "$backup_name" if [ "$verbose" = true ]; then echo "Backed up: $file -> $backup_name" fi else echo "Warning: $file not found" >&2 fi done

echo "Backup completed. Files saved to $backup_dir" `

Example 2: Log Analyzer Script

`bash #!/bin/bash

log_analyzer.sh - Analyze log files

declare -A options=( [lines]=10 [pattern]="" [output]="" [case_sensitive]=true )

Process arguments

while [[ $# -gt 0 ]]; do case $1 in -n|--lines) options[lines]="$2" shift 2 ;; -p|--pattern) options[pattern]="$2" shift 2 ;; -o|--output) options[output]="$2" shift 2 ;; -i|--ignore-case) options[case_sensitive]=false shift ;; -*) echo "Unknown option: $1" >&2 exit 1 ;; *) log_files+=("$1") shift ;; esac done

Validate log files

if [ ${#log_files[@]} -eq 0 ]; then echo "Error: No log files specified" >&2 exit 1 fi

Process each log file

for log_file in "${log_files[@]}"; do if [ ! -f "$log_file" ]; then echo "Warning: $log_file not found" >&2 continue fi echo "Analyzing: $log_file" # Build grep command grep_cmd="grep" if [ "${options[case_sensitive]}" = false ]; then grep_cmd="$grep_cmd -i" fi if [ -n "${options[pattern]}" ]; then if [ -n "${options[output]}" ]; then $grep_cmd "${options[pattern]}" "$log_file" | tail -n "${options[lines]}" >> "${options[output]}" else $grep_cmd "${options[pattern]}" "$log_file" | tail -n "${options[lines]}" fi else if [ -n "${options[output]}" ]; then tail -n "${options[lines]}" "$log_file" >> "${options[output]}" else tail -n "${options[lines]}" "$log_file" fi fi done `

Example 3: System Information Script

`bash #!/bin/bash

sysinfo.sh - Display system information

show_usage() { cat << EOF Usage: $0 [OPTIONS]

Options: -a, --all Show all information -c, --cpu Show CPU information -m, --memory Show memory information -d, --disk Show disk information -n, --network Show network information -s, --services Show running services -h, --help Show this help

Examples: $0 -a # Show all information $0 -c -m # Show CPU and memory info $0 --disk --network # Show disk and network info EOF }

show_cpu() { echo "=== CPU Information ===" lscpu | grep -E "Model name|CPU\(s\)|Thread|Core" echo }

show_memory() { echo "=== Memory Information ===" free -h echo }

show_disk() { echo "=== Disk Information ===" df -h echo }

show_network() { echo "=== Network Information ===" ip addr show | grep -E "inet |link" echo }

show_services() { echo "=== Running Services ===" systemctl list-units --type=service --state=running | head -20 echo }

Default options

show_all=false show_cpu_info=false show_mem_info=false show_disk_info=false show_net_info=false show_svc_info=false

Parse arguments

while [[ $# -gt 0 ]]; do case $1 in -a|--all) show_all=true shift ;; -c|--cpu) show_cpu_info=true shift ;; -m|--memory) show_mem_info=true shift ;; -d|--disk) show_disk_info=true shift ;; -n|--network) show_net_info=true shift ;; -s|--services) show_svc_info=true shift ;; -h|--help) show_usage exit 0 ;; *) echo "Unknown option: $1" >&2 show_usage exit 1 ;; esac done

Show information based on options

if [ "$show_all" = true ]; then show_cpu show_memory show_disk show_network show_services else # Show specific information [ "$show_cpu_info" = true ] && show_cpu [ "$show_mem_info" = true ] && show_memory [ "$show_disk_info" = true ] && show_disk [ "$show_net_info" = true ] && show_network [ "$show_svc_info" = true ] && show_services # If no specific options, show usage if [ "$show_cpu_info" = false ] && [ "$show_mem_info" = false ] && \ [ "$show_disk_info" = false ] && [ "$show_net_info" = false ] && \ [ "$show_svc_info" = false ]; then echo "No options specified. Use -h for help." exit 1 fi fi `

Common Argument Patterns

Pattern Matching Table

| Pattern | Description | Example | |---------|-------------|---------| | $1 in .txt | Match file extension | if [[ "$1" == .txt ]]; then | | [[ $# -eq n ]] | Exact argument count | if [[ $# -eq 2 ]]; then | | [[ $# -lt n ]] | Minimum arguments | if [[ $# -lt 1 ]]; then | | [[ -n "$1" ]] | Non-empty argument | if [[ -n "$1" ]]; then | | [[ -z "$1" ]] | Empty argument | if [[ -z "$1" ]]; then |

Debugging Argument Processing

Debug Script Template

`bash #!/bin/bash

Enable debug mode

set -x # Print commands as they execute set -e # Exit on any error

debug_args() { echo "=== Argument Debug Information ===" echo "Script name: $0" echo "Number of arguments: $#" echo "All arguments (\$@): $@" echo "All arguments (\$): $" echo "Process ID: $" local i=1 for arg in "$@"; do echo "Argument $i: [$arg]" ((i++)) done echo "==========================" }

Call debug function

debug_args "$@"

Your script logic here

`

This comprehensive guide covers all aspects of passing arguments to shell scripts, from basic positional parameters to advanced option processing. The examples demonstrate real-world usage patterns and best practices for creating robust, user-friendly shell scripts that can handle various input scenarios effectively.

Tags

  • Command Line
  • Linux
  • Unix
  • bash
  • shell-scripting

Related Articles

Popular Technical Articles & Tutorials

Explore our comprehensive collection of technical articles, programming tutorials, and IT guides written by industry experts:

Browse all 8+ technical articles | Read our IT blog

Shell Script Arguments: Complete Guide with Examples