# Script Examples [← Back to README](../../README.md) | [Home](Home.md) | [Troubleshooting →](Troubleshooting.md) --- ## Table of Contents - [Basic Examples](#basic-examples) - [Git Automation](#git-automation) - [Development Tools](#development-tools) - [Deployment Scripts](#deployment-scripts) - [System Utilities](#system-utilities) - [Team Examples](#team-examples) - [Advanced Patterns](#advanced-patterns) ## Basic Examples ### Hello World ```bash #!/usr/bin/env bash ### DOC # hello - Simple greeting script # # Usage: dr hello [name] # # Examples: # dr hello # dr hello Alice ### DOC name="${1:-World}" echo "Hello, $name!" ``` ### Interactive Input ```bash #!/usr/bin/env bash ### DOC # prompt - Interactive user input example # # Usage: dr prompt ### DOC read -p "What's your name? " name read -p "What's your favorite color? " color echo "Hello $name! $color is a great color!" ``` ### Argument Parsing ```bash #!/usr/bin/env bash ### DOC # args-demo - Demonstrate argument parsing # # Usage: dr args-demo [options] # # Options: # -v, --verbose Enable verbose output # -f, --force Force operation # -o, --output Output file ### DOC VERBOSE=false FORCE=false OUTPUT="" while [[ $# -gt 0 ]]; do case $1 in -v | --verbose) VERBOSE=true shift ;; -f | --force) FORCE=true shift ;; -o | --output) OUTPUT="$2" shift 2 ;; -*) echo "Unknown option: $1" exit 1 ;; *) FILE="$1" shift ;; esac done [[ "$VERBOSE" == true ]] && echo "Verbose mode enabled" [[ "$FORCE" == true ]] && echo "Force mode enabled" [[ -n "$OUTPUT" ]] && echo "Output file: $OUTPUT" [[ -n "$FILE" ]] && echo "Input file: $FILE" ``` ## Git Automation ### Quick Commit ```bash #!/usr/bin/env bash ### DOC # git/quick-commit - Fast git commit with generated message # # Usage: dr git/quick-commit [message] # # If no message provided, generates one from changes # # Examples: # dr git/quick-commit # dr git/quick-commit "Fix typo" ### DOC set -euo pipefail # Check for changes if [[ -z $(git status --porcelain) ]]; then echo "No changes to commit" exit 0 fi # Generate or use provided message if [[ $# -eq 0 ]]; then # Auto-generate message from changes added=$(git diff --cached --name-only --diff-filter=A | wc -l) modified=$(git diff --cached --name-only --diff-filter=M | wc -l) deleted=$(git diff --cached --name-only --diff-filter=D | wc -l) message="Update: " [[ $added -gt 0 ]] && message+="$added added, " [[ $modified -gt 0 ]] && message+="$modified modified, " [[ $deleted -gt 0 ]] && message+="$deleted deleted" message=${message%, } else message="$*" fi # Stage and commit git add -A git commit -m "$message" echo "✓ Committed: $message" ``` ### Branch Cleanup ```bash #!/usr/bin/env bash ### DOC # git/branch-cleanup - Remove merged branches # # Safely removes local branches that have been merged to main/master # # Usage: dr git/branch-cleanup [--dry-run] # # Options: # --dry-run Show what would be deleted ### DOC set -euo pipefail DRY_RUN=false [[ "${1:-}" == "--dry-run" ]] && DRY_RUN=true # Get default branch DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@') # Get merged branches BRANCHES=$(git branch --merged "$DEFAULT_BRANCH" | grep -v "^[* ] $DEFAULT_BRANCH$" | sed 's/^[ *]*//') if [[ -z "$BRANCHES" ]]; then echo "No merged branches to clean up" exit 0 fi echo "Branches merged to $DEFAULT_BRANCH:" echo "$BRANCHES" if [[ "$DRY_RUN" == true ]]; then echo "" echo "Run without --dry-run to delete these branches" else echo "" read -p "Delete these branches? [y/N] " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then echo "$BRANCHES" | xargs -n 1 git branch -d echo "✓ Deleted merged branches" else echo "Cancelled" fi fi ``` ### PR Create ```bash #!/usr/bin/env bash ### DOC # git/pr-create - Create pull request with template # # Creates a PR with a standard template and opens in browser # # Usage: dr git/pr-create [title] # # Requires: gh (GitHub CLI) ### DOC set -euo pipefail # Check for gh if ! command -v gh &>/dev/null; then echo "Error: GitHub CLI (gh) is required" echo "Install: https://cli.github.com/" exit 1 fi # Get PR title if [[ $# -eq 0 ]]; then # Generate from branch name branch=$(git branch --show-current) title=$(echo "$branch" | sed 's/[-_]/ /g' | sed 's/\b\(.\)/\u\1/g') else title="$*" fi # Create PR body template body=$( cat <<'EOF' ## Summary Brief description of changes ## Type of Change - [ ] Bug fix - [ ] New feature - [ ] Breaking change - [ ] Documentation update ## Testing - [ ] Tests pass locally - [ ] Added new tests - [ ] Updated documentation ## Checklist - [ ] Code follows style guidelines - [ ] Self-review completed - [ ] Comments added where needed EOF ) # Create PR gh pr create --title "$title" --body "$body" --web ``` ## Development Tools ### React Component Generator ```bash #!/usr/bin/env bash ### DOC # dev/react-component - Generate React component boilerplate # # Usage: dr dev/react-component [--typescript] # # Options: # --typescript Generate TypeScript component # # Examples: # dr dev/react-component Button # dr dev/react-component Card --typescript ### DOC set -euo pipefail if [[ $# -eq 0 ]]; then echo "Error: Component name required" exit 1 fi COMPONENT_NAME="$1" USE_TS=false [[ "${2:-}" == "--typescript" ]] && USE_TS=true # File extension EXT="jsx" [[ "$USE_TS" == true ]] && EXT="tsx" # Create component directory mkdir -p "$COMPONENT_NAME" # Component file if [[ "$USE_TS" == true ]]; then cat >"$COMPONENT_NAME/$COMPONENT_NAME.$EXT" < = (props) => { return (

$COMPONENT_NAME Component

); }; EOF else cat >"$COMPONENT_NAME/$COMPONENT_NAME.$EXT" < { return (

$COMPONENT_NAME Component

); }; EOF fi # CSS file cat >"$COMPONENT_NAME/$COMPONENT_NAME.css" <"$COMPONENT_NAME/index.$EXT" <"$COMPONENT_NAME/$COMPONENT_NAME.test.$EXT" < { it('renders without crashing', () => { render(<$COMPONENT_NAME />); expect(screen.getByText('$COMPONENT_NAME Component')).toBeInTheDocument(); }); }); EOF echo "✓ Created $COMPONENT_NAME component in ./$COMPONENT_NAME/" ``` ### API Test Runner ```bash #!/usr/bin/env bash ### DOC # dev/api-test - Run API endpoint tests # # Usage: dr dev/api-test [--method GET|POST|PUT|DELETE] # # Options: # --method HTTP method (default: GET) # --data JSON data for POST/PUT # --token Auth token # # Examples: # dr dev/api-test /users # dr dev/api-test /users --method POST --data '{"name":"John"}' ### DOC set -euo pipefail API_BASE="${API_BASE:-http://localhost:3000/api}" METHOD="GET" DATA="" TOKEN="${API_TOKEN:-}" # Parse arguments ENDPOINT="$1" shift while [[ $# -gt 0 ]]; do case $1 in --method) METHOD="$2" shift 2 ;; --data) DATA="$2" shift 2 ;; --token) TOKEN="$2" shift 2 ;; *) echo "Unknown option: $1" exit 1 ;; esac done # Build curl command CURL_CMD="curl -X $METHOD" CURL_CMD+=" -H 'Content-Type: application/json'" [[ -n "$TOKEN" ]] && CURL_CMD+=" -H 'Authorization: Bearer $TOKEN'" [[ -n "$DATA" ]] && CURL_CMD+=" -d '$DATA'" CURL_CMD+=" ${API_BASE}${ENDPOINT}" # Execute and format echo "Testing: $METHOD $ENDPOINT" echo "Command: $CURL_CMD" echo "---" eval "$CURL_CMD" | jq '.' || eval "$CURL_CMD" ``` ## Deployment Scripts ### Docker Deploy ```bash #!/usr/bin/env bash ### DOC # deploy/docker - Deploy application with Docker # # Usage: dr deploy/docker [--build] # # Arguments: # environment Target environment (dev|staging|prod) # # Options: # --build Rebuild images before deploying # # Examples: # dr deploy/docker staging # dr deploy/docker prod --build ### DOC set -euo pipefail if [[ $# -eq 0 ]]; then echo "Error: Environment required (dev|staging|prod)" exit 1 fi ENV="$1" BUILD=false [[ "${2:-}" == "--build" ]] && BUILD=true # Validate environment case "$ENV" in dev | staging | prod) ;; *) echo "Error: Invalid environment: $ENV" exit 1 ;; esac # Load environment config ENV_FILE=".env.$ENV" if [[ ! -f "$ENV_FILE" ]]; then echo "Error: Environment file not found: $ENV_FILE" exit 1 fi echo "Deploying to $ENV environment..." # Build if requested if [[ "$BUILD" == true ]]; then echo "Building images..." docker-compose -f docker-compose.yml -f docker-compose.$ENV.yml build fi # Deploy echo "Starting containers..." docker-compose -f docker-compose.yml -f docker-compose.$ENV.yml up -d # Health check echo "Waiting for health check..." sleep 5 if docker-compose ps | grep -q "healthy"; then echo "✓ Deployment successful!" docker-compose ps else echo "✗ Health check failed!" docker-compose logs --tail=50 exit 1 fi ``` ### Kubernetes Deploy ```bash #!/usr/bin/env bash ### DOC # deploy/k8s - Deploy to Kubernetes cluster # # Usage: dr deploy/k8s [--namespace prod] # # Arguments: # app Application name # version Version tag # # Options: # --namespace Kubernetes namespace (default: default) # --dry-run Show what would be deployed # # Examples: # dr deploy/k8s myapp v1.2.3 # dr deploy/k8s myapp v1.2.3 --namespace production ### DOC set -euo pipefail if [[ $# -lt 2 ]]; then echo "Error: App name and version required" exit 1 fi APP="$1" VERSION="$2" NAMESPACE="default" DRY_RUN="" shift 2 # Parse options while [[ $# -gt 0 ]]; do case $1 in --namespace) NAMESPACE="$2" shift 2 ;; --dry-run) DRY_RUN="--dry-run=client" shift ;; *) echo "Unknown option: $1" exit 1 ;; esac done echo "Deploying $APP:$VERSION to $NAMESPACE namespace" # Update image kubectl set image deployment/$APP $APP=$APP:$VERSION \ --namespace=$NAMESPACE \ $DRY_RUN if [[ -z "$DRY_RUN" ]]; then # Wait for rollout echo "Waiting for rollout..." kubectl rollout status deployment/$APP \ --namespace=$NAMESPACE \ --timeout=300s echo "✓ Deployment complete!" # Show status kubectl get pods -l app=$APP --namespace=$NAMESPACE fi ``` ## System Utilities ### Backup Script ```bash #!/usr/bin/env bash ### DOC # utils/backup - Backup important directories # # Usage: dr utils/backup [--compress] # # Options: # --compress Compress backup with gzip # --exclude Exclude pattern (can be used multiple times) # # Environment: # BACKUP_DIRS Directories to backup (default: Documents, Pictures) # BACKUP_DEST Backup destination (default: ~/Backups) ### DOC set -euo pipefail COMPRESS=false EXCLUDES=() BACKUP_DIRS="${BACKUP_DIRS:-Documents Pictures}" BACKUP_DEST="${BACKUP_DEST:-$HOME/Backups}" # Parse options while [[ $# -gt 0 ]]; do case $1 in --compress) COMPRESS=true shift ;; --exclude) EXCLUDES+=("--exclude=$2") shift 2 ;; *) echo "Unknown option: $1" exit 1 ;; esac done # Create backup directory TIMESTAMP=$(date +%Y%m%d_%H%M%S) BACKUP_PATH="$BACKUP_DEST/backup_$TIMESTAMP" mkdir -p "$BACKUP_PATH" echo "Starting backup to $BACKUP_PATH" # Backup each directory for dir in $BACKUP_DIRS; do if [[ -d "$HOME/$dir" ]]; then echo "Backing up $dir..." rsync -av "${EXCLUDES[@]}" "$HOME/$dir/" "$BACKUP_PATH/$dir/" else echo "Warning: $dir not found, skipping" fi done # Compress if requested if [[ "$COMPRESS" == true ]]; then echo "Compressing backup..." tar -czf "$BACKUP_PATH.tar.gz" -C "$BACKUP_DEST" "backup_$TIMESTAMP" rm -rf "$BACKUP_PATH" echo "✓ Backup completed: $BACKUP_PATH.tar.gz" else echo "✓ Backup completed: $BACKUP_PATH" fi # Show backup size du -sh "$BACKUP_DEST/backup_$TIMESTAMP"* ``` ### System Info ```bash #!/usr/bin/env bash ### DOC # utils/sysinfo - Display system information # # Usage: dr utils/sysinfo [--json] # # Options: # --json Output in JSON format ### DOC set -euo pipefail JSON_OUTPUT=false [[ "${1:-}" == "--json" ]] && JSON_OUTPUT=true # Gather info HOSTNAME=$(hostname) OS=$(uname -s) KERNEL=$(uname -r) ARCH=$(uname -m) UPTIME=$(uptime -p 2>/dev/null || uptime) CPU=$(grep -m1 "model name" /proc/cpuinfo 2>/dev/null | cut -d: -f2 | xargs) MEMORY=$(free -h 2>/dev/null | awk '/^Mem:/ {print $2}') DISK=$(df -h / | awk 'NR==2 {print $4 " free of " $2}') if [[ "$JSON_OUTPUT" == true ]]; then cat <&2; } success() { green "SUCCESS: $*"; } warning() { yellow "WARNING: $*"; } info() { blue "INFO: $*"; } # Confirmation prompt confirm() { local prompt="${1:-Continue?}" local default="${2:-n}" if [[ "$default" == "y" ]]; then prompt="$prompt [Y/n] " else prompt="$prompt [y/N] " fi read -r -p "$prompt" response response=${response:-$default} [[ "$response" =~ ^[Yy]$ ]] } # Check dependencies require_command() { local cmd="$1" if ! command -v "$cmd" &>/dev/null; then error "$cmd is required but not installed" return 1 fi } # Retry function retry() { local retries="${1:-3}" local delay="${2:-1}" shift 2 local count=0 until "$@"; do count=$((count + 1)) if [[ $count -lt $retries ]]; then warning "Attempt $count failed, retrying in ${delay}s..." sleep "$delay" else error "Failed after $retries attempts" return 1 fi done } ``` ### Team Onboarding Script ```bash #!/usr/bin/env bash ### DOC # team/onboard - Set up new team member environment # # Usage: dr team/onboard # # Sets up: # - Git configuration # - SSH keys # - Tool installation # - Project cloning ### DOC set -euo pipefail if [[ $# -eq 0 ]]; then echo "Error: Email address required" exit 1 fi EMAIL="$1" NAME=$(echo "$EMAIL" | cut -d@ -f1 | sed 's/[._]/ /g' | sed 's/\b\(.\)/\u\1/g') echo "Welcome to the team, $NAME!" echo "This script will set up your development environment." echo "" # Git configuration echo "1. Configuring Git..." git config --global user.email "$EMAIL" git config --global user.name "$NAME" git config --global init.defaultBranch main git config --global pull.rebase true # SSH key echo "2. Setting up SSH key..." if [[ ! -f ~/.ssh/id_ed25519 ]]; then ssh-keygen -t ed25519 -C "$EMAIL" -f ~/.ssh/id_ed25519 -N "" echo "✓ SSH key created" echo "" echo "Add this key to your GitHub account:" cat ~/.ssh/id_ed25519.pub echo "" read -p "Press Enter when you've added the key..." else echo "✓ SSH key already exists" fi # Install tools echo "3. Installing required tools..." TOOLS="jq yq shellcheck" for tool in $TOOLS; do if ! command -v "$tool" &>/dev/null; then echo "Installing $tool..." # Add platform-specific installation else echo "✓ $tool already installed" fi done # Clone projects echo "4. Cloning team projects..." PROJECTS_DIR="$HOME/projects" mkdir -p "$PROJECTS_DIR" REPOS=( "git@github.com:team/main-app.git" "git@github.com:team/api.git" "git@github.com:team/docs.git" ) for repo in "${REPOS[@]}"; do repo_name=$(basename "$repo" .git) if [[ ! -d "$PROJECTS_DIR/$repo_name" ]]; then echo "Cloning $repo_name..." git clone "$repo" "$PROJECTS_DIR/$repo_name" else echo "✓ $repo_name already cloned" fi done # Import team scripts echo "5. Importing team DotRun scripts..." if [[ -f ~/Downloads/team-scripts.tar.gz ]]; then dr collection import ~/Downloads/team-scripts.tar.gz else echo "Download team-scripts.tar.gz and run:" echo " dr collection import ~/Downloads/team-scripts.tar.gz" fi echo "" echo "✓ Onboarding complete!" echo "" echo "Next steps:" echo "1. Review team documentation in $PROJECTS_DIR/docs" echo "2. Run 'dr team/setup-dev' to configure development environment" echo "3. Join #dev-team Slack channel" ``` ## Advanced Patterns ### Parallel Processing ```bash #!/usr/bin/env bash ### DOC # advanced/parallel-process - Process files in parallel # # Usage: dr advanced/parallel-process # # Processes all .log files in parallel using GNU parallel ### DOC set -euo pipefail if [[ $# -eq 0 ]]; then echo "Error: Directory required" exit 1 fi DIR="$1" if ! command -v parallel &>/dev/null; then echo "Error: GNU parallel required" echo "Install: apt/brew install parallel" exit 1 fi process_file() { local file="$1" echo "Processing: $file" # Simulate processing grep -c ERROR "$file" || echo "0 errors" # Real processing would go here # compress, analyze, upload, etc. } export -f process_file # Find and process files in parallel find "$DIR" -name "*.log" -type f \ | parallel -j 4 --progress process_file echo "✓ Processing complete" ``` ### State Machine ```bash #!/usr/bin/env bash ### DOC # advanced/state-machine - Example state machine implementation # # Usage: dr advanced/state-machine # # Demonstrates a simple state machine pattern ### DOC set -euo pipefail # States STATE_INIT="init" STATE_RUNNING="running" STATE_PAUSED="paused" STATE_STOPPED="stopped" # Current state CURRENT_STATE="$STATE_INIT" # State transitions transition() { local from="$1" local to="$2" echo "Transitioning from $from to $to" CURRENT_STATE="$to" # Execute state entry actions case "$to" in "$STATE_RUNNING") echo "Starting process..." ;; "$STATE_PAUSED") echo "Pausing process..." ;; "$STATE_STOPPED") echo "Stopping process..." ;; esac } # State machine loop while true; do echo "Current state: $CURRENT_STATE" echo "Commands: start, pause, resume, stop, quit" read -p "> " command case "$CURRENT_STATE" in "$STATE_INIT") case "$command" in start) transition "$STATE_INIT" "$STATE_RUNNING" ;; quit) break ;; *) echo "Invalid command in INIT state" ;; esac ;; "$STATE_RUNNING") case "$command" in pause) transition "$STATE_RUNNING" "$STATE_PAUSED" ;; stop) transition "$STATE_RUNNING" "$STATE_STOPPED" ;; *) echo "Invalid command in RUNNING state" ;; esac ;; "$STATE_PAUSED") case "$command" in resume) transition "$STATE_PAUSED" "$STATE_RUNNING" ;; stop) transition "$STATE_PAUSED" "$STATE_STOPPED" ;; *) echo "Invalid command in PAUSED state" ;; esac ;; "$STATE_STOPPED") case "$command" in start) transition "$STATE_STOPPED" "$STATE_RUNNING" ;; quit) break ;; *) echo "Invalid command in STOPPED state" ;; esac ;; esac done echo "State machine terminated" ``` --- **Want more examples?** Check out: - [Git Examples](#git-automation) - Advanced Git automation - [Development Examples](#development-tools) - Development productivity scripts - [Team Examples](#team-examples) - Collaboration examples [← Back to README](../../README.md) | [Home](Home.md) | [Troubleshooting →](Troubleshooting.md) | [Top ↑](#script-examples)