Stage 2 · Tools
Bash Fundamentals
Shell Basics
Shell types, shebang lines, command parsing, and exit codes — the foundation of every script.
What Is a Shell?
A shell is a program that reads commands from the user or a file and executes them. It acts as an interface between you and the operating system kernel. When you type a command in a terminal, the shell parses your input, finds the corresponding program, and runs it.
The shell also provides programming constructs — variables, loops, conditionals, functions — that let you combine simple commands into powerful automation. This is what makes shell scripting so valuable for DevOps and system administration.
Shell Types
Not all shells are the same. Different shells exist with different features, syntax, and performance characteristics. The three most common are Bash, Zsh, and Dash.
| Shell | Default On | Key Features |
|---|---|---|
| Bash | Most Linux distros | Full POSIX + arrays, [[ ]] tests, process substitution |
| Zsh | macOS | Bash features + better globbing, plugin ecosystem |
| Dash | Debian/Ubuntu (as sh) | Fast, minimal — POSIX only, no arrays |
Run echo $SHELL to see your login shell, or ps -p $$ to see the current interactive shell. Use chsh -s /bin/bash to switch if needed.
Shebang Lines
Every shell script should start with a shebang — a special line that tells the system which interpreter to use. The shebang must be the very first line of the file.
#!/bin/bash # Direct path to Bash
#!/usr/bin/env bash # Use env to find Bash in PATH (portable)
#!/bin/sh # POSIX shell (Dash on Debian, Bash elsewhere)
#!/usr/bin/env zsh # ZshThe #!/usr/bin/env bash form is preferred because it works even if Bash is installed in a non-standard location. It searches your PATH for the interpreter.
Without a shebang, the system uses the default shell (often Dash on Debian/Ubuntu). This can cause subtle bugs — Bash features like arrays and [[ ]] will fail silently or throw syntax errors.
Command Parsing
When you type a command, the shell performs several steps before execution. Understanding this process helps you write correct scripts and debug confusing behavior.
- Tokenization — The shell splits the input line into words using whitespace and special characters.
- Variable expansion —
$VARand{VAR}are replaced with their values. - Command substitution —
commandand $(command) are replaced with the command's output. - Globbing — Patterns like
*.txtare expanded to matching filenames. - Redirection —
<,>,>>,|are set up before the command runs. - Execution — The shell finds and runs the command.
NAME="world"
echo "Hello, $NAME" # Variable expansion
echo "Today is $(date +%F)" # Command substitution
echo *.ts # Glob expansionEach step transforms your input before the command actually runs. This is why quoting matters — double quotes prevent globbing and word splitting, while single quotes prevent all expansion.
Exit Codes
Every command returns an exit code (also called a return status) when it finishes. Exit code 0 means success. Any non-zero value indicates failure. This is the primary way scripts communicate success or failure.
ls /tmp
echo $? # 0 — success
ls /nonexistent 2>/dev/null
echo $? # 2 — "No such file or directory"
false
echo $? # 1 — always fails
true
echo $? # 0 — always succeedsThe special variable $? holds the exit code of the most recently executed command. Use it in conditionals to make decisions based on command results.
Unlike many programming languages where 0 means false/failure, in Unix shells 0 means success. Non-zero means failure. This is consistent across the entire Unix ecosystem — grep, find, curl, make, and every other tool follows this convention.
Writing Your First Script
Let's combine everything into a real script. Create a file, add the shebang, write your commands, make it executable, and run it.
#!/usr/bin/env bash
# A simple introductory script
NAME="${1:-World}"
echo "Hello, $NAME!"
echo "Current user: $(whoami)"
echo "Current directory: $(pwd)"
echo "Date: $(date '+%Y-%m-%d %H:%M:%S')"This script takes an optional argument (your name), or defaults to 'World'. It demonstrates variable assignment, command substitution, and parameter expansion.
chmod +x hello.sh # Make it executable
./hello.sh # Hello, World!
./hello.sh Alice # Hello, Alice!The chmod +x command adds execute permission. Without it, running ./hello.sh would give a 'Permission denied' error. You can also run it without execute permission using bash hello.sh.
Running ./script.sh uses the shebang to select the interpreter. Running bash script.sh ignores the shebang entirely. For production scripts, always use ./script.sh so the shebang works as intended.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.