Use when writing or modifying Bash/shell scripts. Covers script structure, variables, quoting, conditionals, and loops with modern best practices.
View on GitHubTheBushidoCollective/han
jutsu-shellcheck
January 24, 2026
Select agents to install to:
npx add-skill https://github.com/TheBushidoCollective/han/blob/main/jutsu/jutsu-shellcheck/skills/shell-scripting-fundamentals/SKILL.md -a claude-code --skill shell-scripting-fundamentalsInstallation paths:
.claude/skills/shell-scripting-fundamentals/# Shell Scripting Fundamentals
Core patterns and best practices for writing robust, maintainable shell scripts.
## Script Structure
Always start scripts with a proper shebang and safety options:
```bash
#!/usr/bin/env bash
set -euo pipefail
# Script description here
```
### Safety Options Explained
- `set -e`: Exit on any command failure
- `set -u`: Error on undefined variables
- `set -o pipefail`: Pipeline fails if any command fails
## Variables
### Declaration and Assignment
```bash
# No spaces around =
name="value"
# readonly for constants
readonly CONFIG_DIR="/etc/myapp"
# local in functions
my_function() {
local result="computed"
echo "$result"
}
```
### Always Quote Variables
```bash
# Good - prevents word splitting and glob expansion
echo "$variable"
cp "$source" "$destination"
# Bad - can break on spaces or special characters
echo $variable
cp $source $destination
```
### Default Values
```bash
# Use default if unset
name="${NAME:-default}"
# Use default if unset or empty
name="${NAME:-}"
# Assign default if unset
: "${NAME:=default}"
# Error if unset
: "${REQUIRED_VAR:?Error: REQUIRED_VAR must be set}"
```
## Conditionals
### Test Syntax
```bash
# Modern syntax - preferred
if [[ -f "$file" ]]; then
echo "File exists"
fi
# String comparison
if [[ "$string" == "value" ]]; then
echo "Match"
fi
# Numeric comparison
if (( count > 10 )); then
echo "Greater than 10"
fi
# Regex matching
if [[ "$input" =~ ^[0-9]+$ ]]; then
echo "Numeric input"
fi
```
### Common Test Operators
| Operator | Description |
|----------|-------------|
| `-f` | File exists and is regular file |
| `-d` | Directory exists |
| `-e` | Path exists |
| `-r` | Readable |
| `-w` | Writable |
| `-x` | Executable |
| `-z` | String is empty |
| `-n` | String is not empty |
## Loops
### For Loops
```bash
# Iterate over list
for item in one two three; do
echo "$item"
done
# Iterate over files (use glob, not ls)
for file in *.txt; do
[[ -e