Loading...
Loading...
Write robust, portable shell scripts with proper error handling, argument parsing, and testing. Use when automating system tasks, building CI/CD scripts, or creating container entrypoints.
npx skill4agent add ancoleman/ai-design-components shell-scripting<(cmd)references/portability-guide.md#!/bin/bash
set -euo pipefail
# -e: Exit on error
# -u: Exit on undefined variable
# -o pipefail: Pipeline fails if any command fails#!/bin/bash
if ! command_that_might_fail; then
echo "Error: Command failed" >&2
exit 1
fi#!/bin/bash
set -euo pipefail
TEMP_FILE=$(mktemp)
cleanup() {
rm -f "$TEMP_FILE"
}
trap cleanup EXITreferences/error-handling.md#!/bin/bash
while getopts "hvf:o:" opt; do
case "$opt" in
h) usage ;;
v) VERBOSE=true ;;
f) INPUT_FILE="$OPTARG" ;;
o) OUTPUT_FILE="$OPTARG" ;;
*) usage ;;
esac
done
shift $((OPTIND - 1))#!/bin/bash
while [[ $# -gt 0 ]]; do
case "$1" in
--help) usage ;;
--verbose) VERBOSE=true; shift ;;
--file) INPUT_FILE="$2"; shift 2 ;;
--file=*) INPUT_FILE="${1#*=}"; shift ;;
*) break ;;
esac
donereferences/argument-parsing.md# Default values
${var:-default} # Use default if unset
${var:=default} # Assign default if unset
: "${API_KEY:?Error: required}" # Error if unset
# String manipulation
${#var} # String length
${var:offset:length} # Substring
${var%.txt} # Remove suffix
${var##*/} # Basename
${var/old/new} # Replace first
${var//old/new} # Replace all
# Case conversion (Bash 4+)
${var^^} # Uppercase
${var,,} # Lowercasereferences/parameter-expansion.md# Extract field
name=$(curl -sSL https://api.example.com/user | jq -r '.name')
# Filter array
active=$(jq '.users[] | select(.active) | .name' data.json)
# Check existence
if ! echo "$json" | jq -e '.field' >/dev/null; then
echo "Error: Field missing" >&2
fi# Read value (yq v4)
host=$(yq eval '.database.host' config.yaml)
# Update in-place
yq eval '.port = 5432' -i config.yaml
# Convert to JSON
yq eval -o=json config.yaml# awk: Extract columns
awk -F',' '{print $1, $3}' data.csv
# sed: Replace text
sed 's/old/new/g' file.txt
# grep: Pattern match
grep -E "ERROR|WARN" logfile.txtreferences/common-utilities.md# Check script
shellcheck script.sh
# POSIX compliance
shellcheck --shell=sh script.sh
# Exclude warnings
shellcheck --exclude=SC2086 script.sh#!/usr/bin/env bats
@test "script runs successfully" {
run ./script.sh --help
[ "$status" -eq 0 ]
[ "${lines[0]}" = "Usage: script.sh [OPTIONS]" ]
}
@test "handles missing argument" {
run ./script.sh
[ "$status" -eq 1 ]
[[ "$output" =~ "Error" ]]
}bats test/references/testing-guide.md#!/bin/bash
set -euo pipefail
# Check required commands
command -v jq >/dev/null 2>&1 || {
echo "Error: jq required" >&2
exit 1
}
# Check environment variables
: "${API_KEY:?Error: API_KEY required}"
# Check files
[ -f "$CONFIG_FILE" ] || {
echo "Error: Config not found: $CONFIG_FILE" >&2
exit 1
}
# Quote all variables
echo "Processing: $file" # ❌ Unquoted
echo "Processing: \"$file\"" # ✅ Quoted# sed in-place
sed -i '' 's/old/new/g' file.txt # macOS
sed -i 's/old/new/g' file.txt # Linux
# Portable: Use temp file
sed 's/old/new/g' file.txt > file.txt.tmp
mv file.txt.tmp file.txt
# readlink
readlink -f /path # Linux only
cd "$(dirname "$0")" && pwd # Portablereferences/portability-guide.md#!/bin/bash
set -euo pipefail
readonly SCRIPT_NAME="$(basename "$0")"
readonly SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
TEMP_DIR=""
cleanup() {
local exit_code=$?
rm -rf "$TEMP_DIR"
exit "$exit_code"
}
trap cleanup EXIT
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*" >&2
}
main() {
# Check dependencies
command -v jq >/dev/null 2>&1 || exit 1
# Parse arguments
# Validate input
# Process
# Report results
log "Completed successfully"
}
main "$@"examples/production-template.sh# macOS
brew install jq yq shellcheck bats-core
# Ubuntu/Debian
apt-get install jq shellcheckreferences/error-handling.mdreferences/argument-parsing.mdreferences/parameter-expansion.mdreferences/portability-guide.mdreferences/testing-guide.mdreferences/common-utilities.mdexamples/production-template.shexamples/getopts-basic.shexamples/getopts-advanced.shexamples/long-options.shexamples/error-handling.shexamples/json-yaml-processing.shscripts/lint-script.shscripts/test-script.sh