shell-scripting — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited shell-scripting (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Provides patterns and best practices for writing maintainable shell scripts with error handling, argument parsing, and portability considerations. Covers POSIX sh vs Bash decision-making, parameter expansion, integration with common utilities (jq, yq, awk), and testing with ShellCheck and Bats.
Use shell scripting when:
Consider Python/Go instead when:
Use POSIX sh (#!/bin/sh) when:
Use Bash (#!/bin/bash) when:
<(cmd) usefulFor detailed comparison and testing strategies, see 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 failsUse for production automation, CI/CD scripts, and critical operations.
#!/bin/bash
if ! command_that_might_fail; then
echo "Error: Command failed" >&2
exit 1
fiUse for custom error messages and interactive scripts.
#!/bin/bash
set -euo pipefail
TEMP_FILE=$(mktemp)
cleanup() {
rm -f "$TEMP_FILE"
}
trap cleanup EXITUse for guaranteed cleanup of temporary files, locks, and resources.
For comprehensive error patterns, see references/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
doneFor hybrid approaches and validation patterns, see references/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,,} # LowercaseFor complete expansion patterns and array handling, see references/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.txtFor detailed examples and best practices, see references/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" ]]
}Run tests:
bats test/For CI/CD integration and debugging techniques, see 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 # PortableFor complete platform differences, see references/portability-guide.md.
System Administration: Cron jobs, log rotation, backup automation Build/Deployment: CI/CD pipelines, Docker builds, deployments Development Tooling: Project setup, test runners, code generators Container Entrypoints: Initialization, signal handling, configuration
#!/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 "$@"For complete production template, see examples/production-template.sh.
Core Tools:
Installation:
# macOS
brew install jq yq shellcheck bats-core
# Ubuntu/Debian
apt-get install jq shellcheckReference Files:
references/error-handling.md - Comprehensive error patternsreferences/argument-parsing.md - Advanced parsing techniquesreferences/parameter-expansion.md - Complete expansion referencereferences/portability-guide.md - POSIX vs Bash differencesreferences/testing-guide.md - ShellCheck and Bats guidereferences/common-utilities.md - jq, yq, awk, sed usageExample Scripts:
examples/production-template.sh - Production-ready templateexamples/getopts-basic.sh - Simple getopts usageexamples/getopts-advanced.sh - Complex option handlingexamples/long-options.sh - Manual long option parsingexamples/error-handling.sh - Error handling patternsexamples/json-yaml-processing.sh - jq/yq examplesUtility Scripts:
scripts/lint-script.sh - ShellCheck wrapper for CIscripts/test-script.sh - Bats wrapper for CI~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.