---
name: bash-development
description: This skill should be used when the user asks to "write a bash script", "create a shell script", "implement bash function", "parse arguments in bash", "handle errors in bash", or mentions bash development, shell scripting, script templates, or modern bash patterns.
enabled: false
source: github:Jamie-BitFlight/claude_skills
imported-from: github:Jamie-BitFlight/claude_skills
---

# Bash Development

Core patterns and best practices for Bash 5.1+ script development. Provides modern bash idioms, error handling, argument parsing, and pure-bash alternatives to external commands.

## Script Foundation

Every script starts with the essential header:

```bash
#!/usr/bin/env bash
set -euo pipefail
```

**set options explained:**

- `-e` - Exit immediately on command failure
- `-u` - Treat unset variables as errors
- `-o pipefail` - Pipeline fails if any command fails

### Script Metadata Pattern

```bash
SCRIPT_NAME=$(basename "${BASH_SOURCE[0]}")
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
readonly SCRIPT_VERSION="1.0.0"
readonly SCRIPT_NAME SCRIPT_DIR
```

## Error Handling

Implement trap-based error handling for robust scripts.

[Code examples](./references/code-examples.md#error-handling)

## Argument Parsing

Standard argument parsing template.

[Code examples](./references/code-examples.md#argument-parsing)

## Variable Best Practices

**Always use curly braces and quote variables:**

```bash
# Correct
"${variable}"
"${array[@]}"

# Incorrect
$variable
${array[*]}  # Use [@] for proper iteration
```

**Use readonly for constants:**

```bash
readonly CONFIG_FILE="/etc/app/config"
readonly -a VALID_OPTIONS=("opt1" "opt2" "opt3")
```

**Note:** Never use `readonly` in sourced scripts - it causes errors on re-sourcing.

## String Operations (Pure Bash)

Prefer native bash parameter expansion over external tools:

```bash
# Trim whitespace
trimmed="${string#"${string%%[![:space:]]*}"}"
trimmed="${trimmed%"${trimmed##*[![:space:]]}"}"

# Lowercase/Uppercase (Bash 4+)
lower="${string,,}"
upper="${string^^}"

# Substring extraction
substring="${string:0:10}"      # First 10 chars
suffix="${string: -5}"          # Last 5 chars

# Replace patterns
replaced="${string//old/new}"   # Replace all
replaced="${string/old/new}"    # Replace first

# Strip prefix/suffix
no_prefix="${string#prefix}"    # Shortest match
no_prefix="${string##*/}"       # Longest match (basename)
no_suffix="${string%suffix}"    # Shortest match
no_suffix="${string%%/*}"       # Longest match
```

## Array Operations

```bash
# Declaration
declare -a indexed_array=()
declare -A assoc_array=()

# Safe iteration with nullglob
shopt -s nullglob
for file in *.txt; do
    process "${file}"
done
shopt -u nullglob

# Array length
length="${#array[@]}"

# Append element
array+=("new_element")

# Iterate with index
for i in "${!array[@]}"; do
    printf '%d: %s\n' "${i}" "${array[i]}"
done
```

## File Operations

```bash
# Read file to string
content="$(<"${file}")"

# Read file to array (Bash 4+)
mapfile -t lines < "${file}"

# Check file conditions
[[ -f "${file}" ]]    # Regular file exists
[[ -d "${dir}" ]]     # Directory exists
[[ -r "${file}" ]]    # Readable
[[ -w "${file}" ]]    # Writable
[[ -x "${file}" ]]    # Executable
[[ -s "${file}" ]]    # Non-empty

# Safe temp file creation
temp_file=$(mktemp)
trap 'rm -f "${temp_file}"' EXIT
```

## Conditional Expressions

Use `[[ ]]` for conditionals (bash-specific, more powerful):

```bash
# String comparisons
[[ "${var}" == "value" ]]       # Equality
[[ "${var}" == pattern* ]]     # Glob matching
[[ "${var}" =~ ^regex$ ]]      # Regex matching

# Numeric comparisons
(( num > 10 ))                  # Arithmetic comparison
[[ "${num}" -gt 10 ]]          # Traditional syntax

# Compound conditions
[[ -f "${file}" && -r "${file}" ]]
[[ "${opt}" == "a" || "${opt}" == "b" ]]
```

## Utility Functions

[Code examples](./references/code-examples.md#utility-functions)

## Performance Guidelines

- Use builtins over external commands when possible
- Batch operations instead of loops for large datasets
- Use `printf` over `echo` for portability and control
- Avoid unnecessary subshells in tight loops
- Use `[[ ]]` over `[ ]` for string comparisons

## Additional Resources

### Reference Files

For detailed patterns and examples:

- **[bash_example_file.sh](./references/bash_example_file.sh)** - Complete script template
- **[bash_example_includes.bash](./references/bash_example_includes.bash)** - Reusable utility functions
- **[bash-agent-notes.markdown](./references/bash-agent-notes.markdown)** - Context-aware review guidance
- **[pure-bash-bible-strings.md](./references/pure-bash-bible-strings.md)** - String manipulation patterns
- **[pure-bash-bible-arrays.md](./references/pure-bash-bible-arrays.md)** - Array operations
- **[pure-bash-bible-files.md](./references/pure-bash-bible-files.md)** - File handling patterns
- **[pure-bash-bible-variables.md](./references/pure-bash-bible-variables.md)** - Parameter expansion reference
