Parsing Command Line Arguments in Linux Using Shift

<span>shift</span> is a built-in command in <span>Bash</span> that shifts the positional parameters to the left, reassigning the values of <span>$1</span>, <span>$2</span>, <span>$3</span>, etc.

$ bash -c "help shift"
shift: shift [n]
    The positional parameters from $N+1 ... are renamed to $1 ...  If N is
    not given, it is assumed to be 1.

It is a core tool for handling <span>command line arguments</span>.

shift [n]  # n is the number of positions to shift, default is 1, indexing starts at 1.

1. Quick Start

First, let’s introduce two special variables in <span>Bash</span>: <span>$@</span><span>$#</span>:

Variable Meaning Example (./test.sh a “b c” d)
$# Number of parameters 3
$@ All parameters a “b c” d (3 independent parameters)

<span>test.sh</span> file content is as follows:

# Original parameters
echo "All parameters: $@"
echo "Number of parameters: $#"

echo "\$1: $1, \$2: $2, \$3: $3, \$4: $4"

# Shift left by one position
shift

echo "Parameters after shift: $@"
echo "Number of parameters after shift: $#"

echo "\$1: $1, \$2: $2, \$3: $3, \$4: $4"

<span>Run it like this:</span>

$ work ./test.sh -a 1 -b 2

All parameters: -a 1 -b 2
Number of parameters: 4
\$1: -a, \$2: 1, \$3: -b, \$4: 2

Parameters after shift: 1 -b 2
Number of parameters after shift: 3
\$1: 1, \$2: -b, \$3: 2, \$4:

<span>The effect of the shift command is similar to:</span>

Command $1 $2 $3 $4 $# $@
Initial arg1 arg2 arg3 arg4 4 arg1 arg2 arg3 arg4
shift arg2 arg3 arg4 empty 3 arg2 arg3 arg4
shift 3 empty empty empty empty 0 empty

2. Template Code for Parsing Command Line Arguments

# Default values
verbose=false
output_dir="."
files=()

# Show help
show_help() {
    echo "Usage: $0 [options] [files...]"
    echo "Options:"
    echo "  -h, --help     Show help"
    echo "  -v, --verbose  Verbose output"
    echo "  -o, --output   Output directory"
}

# Parse parameters
while [ $# -gt 0 ]; do
    case "$1" in
        -h|--help)
            show_help
            exit 0
            ;;
        -v|--verbose)
            verbose=true
            echo "Verbose mode: enabled"
            shift
            ;;
        -o|--output)
            output_dir="$2"
            echo "Output directory: $output_dir"
            shift 2
            ;;
        -* )
            echo "Error: Unknown option $1" &gt;&amp;2
            exit 1
            ;;
        *)
            files+=("$1")
            shift
            ;;
    esac
done

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

echo "Starting to process ${#files[@]} files:"
for file in "${files[@]}"; do
    if [ -f "$file" ]; then
        echo "Processing: $file"
        # Here you can add actual file processing logic
        # For example: cp "$file" "$output_dir/"
    else
        echo "Warning: File does not exist $file"
    fi
done

echo "Processing complete"

Save the above code to a file: <span>util.sh</span>, and then test it:

# Basic usage
./util.sh file1.txt file2.txt

# With options
./util.sh -v -o ./output file1.txt file2.txt

# Show help
./util.sh --help

Ok. I believe you have learned how to use it.

Leave a Comment