Shell Scripting Essentials: Variable Management and Conditional Evaluation
A shell script aggregates commands and control structures within a text file. While the .sh extension is conventional, the shebang directive at the file header determines the execution interpreter:
#!/bin/bash
echo "Initialization sequence started"
Execution Contexts
Scripts execute through three distinct mechanisms with different scoping behaviors:
# Approach 1: Explicit interpreter (spawns subshell)
bash ./script.sh
# Approach 2: Direct invocation requires execute permission
chmod +x ./script.sh
./script.sh
# Approach 3: Source execution (current shell context)
source ./script.sh
# Or equivalently:
. ./script.sh
The first two methods create child processes, isolating environment modifications from the parent shell. Sourcing executes within the current shell session, preserving variable assignments and directory changes after termination. Verify process relationships using ps -f, where child shells display their parent's PID (PPID).
Variable Scope and Persistence
Shell variables are untyped strings classified by scope. Local variables default to the current shell instance:
# Assignment (no spaces around =)
iteration_count=5
deployment_env="production"
Environment variables propagate to subprocesses via export:
export deployment_env
export LOG_PATH=/var/log/app
Child processes inherit exported values, but modifications within subprocesses do not affect parent scope. To enforce immutability:
readonly MAX_CONNECTIONS=100
# Unset removes variables (invalid for readonly)
unset iteration_count
Inspect global variables using env or query specific values: echo $HOME.
Positional and Special Parameters
Runtime arguments populate positional parameters:
#!/bin/bash
# handler.sh
echo "Executing: $0"
echo "Target host: $1"
echo "Port number: $2"
echo "Argument count: $#"
Invocation: ./handler.sh database.local 5432
Special parameter distinctions:
$*expands to a single word containing all arguments$@expands to separate quoted arguments (preserving embedded spaces)$?stores the exit code of the last command (0 indicates success)
ping -c 1 unreachable.host
echo "Exit status: $?"
Arithmetic Operations
Mathematical evaluation requires explicit syntax since variables store strings:
#!/bin/bash
length=25
breadth=10
# Modern double-parentheses syntax
area=$(( length * breadth ))
# Legacy square-bracket syntax (deprecated)
perimeter=$[ 2 * (length + breadth) ]
echo "Computed area: $area"
Suported operators include +, -, *, /, % (modulo), and ** (exponentiation).
Conditional Expressions
The test command or its bracket notation [ evaluates conditions, returning exit code 0 for true. Critical syntax requirement: spaces must separate brackets and operands.
[ "$iteration_count" -gt 0 ]
echo "Test result: $?" # 0 if true, 1 if false
Integer comparison oeprators:
-eq(equal),-ne(not equal)-lt(less than),-le(less than or equal)-gt(greater than),-ge(greater than or equal)
String evaluations:
[ "$deployment_env" = "production" ] && echo "Live environment"
[ "$USER" != "root" ] || echo "Root access confirmed"
File system tests:
-e: path exists-f: regular file-d: directory-r,-w,-x: read, write, execute permissions
[ -x ./deploy.sh ] || echo "Script lacks execution permission"
[ -d /tmp/backups ] || mkdir -p /tmp/backups
Logical Composition
Chain conditions using control operators:
# Logical AND: proceed only if prerequisite succeeds
[ -f "$config_file" ] && [ -r "$config_file" ] && echo "Configuration readable"
# Logical OR: execute alternative on failure
[ -z "$API_KEY" ] && echo "Warning: API key not set"
# Ternary pattern
[ "$deployment_env" = "production" ] && execute_safe_mode || execute_verbose_mode
The [ construct is a builtin command, not syntax, requiring whitespace delimiters. For pattern matching and safer null handling, [[ ]] provides extended functionality, though single brackets remain POSIX-complient for portability.