<< All versions
Skill v1.0.1
currentAutomated scan100/100thebushidocollective/han/shell-scripting-fundamentals
4 files
──Details
PublishedSeptember 28, 2026 at 09:11 PM
Content Hashsha256:3b4ecb9e53ac9b61...
Git SHA19caa51d5fd1
Bump Typepatch
──Files
Files (1 file, 3.8 KB)
SKILL.md3.8 KBactive
SKILL.md · 223 lines · 3.8 KB
version: "1.0.1" name: shell-scripting-fundamentals user-invocable: false description: Use when writing or modifying Bash/shell scripts. Covers script structure, variables, quoting, conditionals, and loops with modern best practices. allowed-tools:
- Read
- Write
- Edit
- Bash
- Grep
- Glob
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 bashset -euo pipefail# Script description here
Safety Options Explained
set -e: Exit on any command failureset -u: Error on undefined variablesset -o pipefail: Pipeline fails if any command fails
Variables
Declaration and Assignment
bash
# No spaces around =name="value"# readonly for constantsreadonly CONFIG_DIR="/etc/myapp"# local in functionsmy_function() {local result="computed"echo "$result"}
Always Quote Variables
bash
# Good - prevents word splitting and glob expansionecho "$variable"cp "$source" "$destination"# Bad - can break on spaces or special charactersecho $variablecp $source $destination
Default Values
bash
# Use default if unsetname="${NAME:-default}"# Use default if unset or emptyname="${NAME:-}"# Assign default if unset: "${NAME:=default}"# Error if unset: "${REQUIRED_VAR:?Error: REQUIRED_VAR must be set}"
Conditionals
Test Syntax
bash
# Modern syntax - preferredif [[ -f "$file" ]]; thenecho "File exists"fi# String comparisonif [[ "$string" == "value" ]]; thenecho "Match"fi# Numeric comparisonif (( count > 10 )); thenecho "Greater than 10"fi# Regex matchingif [[ "$input" =~ ^[0-9]+$ ]]; thenecho "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 listfor item in one two three; doecho "$item"done# Iterate over files (use glob, not ls)for file in *.txt; do[[ -e "$file" ]] || continue # Handle no matchesprocess "$file"done# C-style for loopfor (( i = 0; i < 10; i++ )); doecho "$i"done
While Loops
bash
# Read lines from filewhile IFS= read -r line; doecho "$line"done < "$filename"# Read with process substitutionwhile IFS= read -r line; doecho "$line"done < <(some_command)
Arrays
bash
# Declare arraydeclare -a files=()# Add elementsfiles+=("file1.txt")files+=("file2.txt")# Iterate all elementsfor file in "${files[@]}"; doecho "$file"done# Get array lengthecho "${#files[@]}"# Access by indexecho "${files[0]}"
Command Substitution
bash
# Modern syntax - preferredresult=$(command)# Nested substitutionresult=$(echo $(date))# Avoid legacy backticksresult=`command` # Don't use this
Functions
bash
# Function definitionprocess_file() {local file="$1"local output_dir="${2:-./output}"if [[ ! -f "$file" ]]; thenecho "Error: File not found: $file" >&2return 1fi# Process the filecp "$file" "$output_dir/"}# Call with argumentsprocess_file "input.txt" "/tmp/output"
Best Practices Summary
- Always use
#!/usr/bin/env bashfor portability - Enable strict mode:
set -euo pipefail - Quote all variable expansions
- Use
[[ ]]instead of[ ]for tests - Use
$(command)instead of backticks - Declare local variables in functions
- Use arrays for lists of items
- Check command existence before use:
command -v cmd >/dev/null