Skip to main content

shell-bash

Shell scripting and Bash programming patterns

来源信息

仓库
miles990/claude-software-skills
最近来源活动
2026年1月8日 02:34
检测到的 SKILL.md 语言
英语
星标
25
分支
6

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

文件资源管理器
3 个文件

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
shell-bash
description
Shell scripting and Bash programming patterns
domain
programming-languages
version
1.0.0
tags
["bash","shell","scripting","automation","cli"]
triggers
{"keywords":{"primary":["bash","shell","sh","zsh","script","terminal","cli"],"secondary":["grep","sed","awk","pipe","cron","automation","makefile"]},"context_boost":["devops","linux","unix","automation","sysadmin"],"context_penalty":["web","frontend","mobile","gui"],"priority":"medium"}
# Shell & Bash Scripting ## Overview Shell scripting patterns for automation, system administration, and CLI tools. --- ## Script Fundamentals ### Script Structure ```bash #!/usr/bin/env bash # # Script: backup.sh # Description: Backup files to remote server # Usage: ./backup.sh [options] <source> <destination> # set -euo pipefail # Exit on error, undefined vars, pipe failures IFS=$'\n\t' # Safer word splitting # Constants readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")" readonly LOG_FILE="/var/log/${SCRIPT_NAME%.sh}.log" # Default values VERBOSE=false DRY_RUN=false COMPRESS=true # Cleanup on exit cleanup() { local exit_code=$? # Cleanup temporary files rm -f "${TEMP_FILE:-}" exit "$exit_code" } trap cleanup EXIT # Logging functions log() { local level="$1" shift echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $*" | tee -a "$LOG_FILE" } info() { log "INFO" "$@"; } warn() { log "WARN" "$@" >&2; } error() { log "ERROR" "$@" >&2; } debug() { [[ "$VERBOSE" == true ]] && log "DEBUG" "$@" || true; } die() { error "$@" exit 1 } # Usage usage() { cat <<EOF Usage: $SCRIPT_NAME [options] <source> <destination> Options: -v, --verbose Enable verbose output -n, --dry-run Show what would be done -h, --help Show this help message Examples: $SCRIPT_NAME /data /backup $SCRIPT_NAME -v --dry-run /home/user /mnt/backup EOF } # Main function main() { parse_args "$@" validate_inputs perform_backup } # Run main if script is executed directly if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then main "$@" fi ``` ### Argument Parsing ```bash # Using getopts (POSIX) parse_args_getopts() { while getopts ":vnh" opt; do case $opt in v) VERBOSE=true ;; n) DRY_RUN=true ;; h) usage; exit 0 ;; \?) die "Invalid option: -$OPTARG" ;; :) die "Option -$OPTARG requires an argument" ;; esac done shift $((OPTIND - 1)) SOURCE="${1:-}" DESTINATION="${2:-}" } # Using manual parsing (supports long options) parse_args() { while [[ $# -gt 0 ]]; do case "$1" in -v|--verbose) VERBOSE=true shift ;; -n|--dry-run) DRY_RUN=true shift ;; -c|--compress) COMPRESS=true shift ;; --no-compress) COMPRESS=false shift ;; -h|--help) usage exit 0 ;; --) shift break ;; -*) die "Unknown option: $1" ;; *) break ;; esac done # Positional arguments SOURCE="${1:-}" DESTINATION="${2:-}" } # Validation validate_inputs() { [[ -z "$SOURCE" ]] && die "Source path is required" [[ -z "$DESTINATION" ]] && die "Destination path is required" [[ -e "$SOURCE" ]] || die "Source does not exist: $SOURCE" } ``` --- ## Variables and Data ### Variable Operations ```bash # Variable assignment name="John" readonly CONSTANT="immutable" # Default values name="${name:-default}" # Use default if unset or empty name="${name:=default}" # Assign default if unset or empty name="${name:+alternative}" # Use alternative if set and non-empty name="${name:?error message}" # Error if unset or empty # String manipulation str="Hello, World!" echo "${str:0:5}" # "Hello" (substring) echo "${str: -6}" # "World!" (last 6 chars) echo "${#str}" # 13 (length) echo "${str/World/Bash}" # "Hello, Bash!" (replace first) echo "${str//o/0}" # "Hell0, W0rld!" (replace all) echo "${str#Hello, }" # "World!" (remove prefix) echo "${str%!}" # "Hello, World" (remove suffix) echo "${str^^}" # "HELLO, WORLD!" (uppercase) echo "${str,,}" # "hello, world!" (lowercase) # Parameter expansion filename="/path/to/file.tar.gz" echo "${filename##*/}" # "file.tar.gz" (basename) echo "${filename%/*}" # "/path/to" (dirname) echo "${filename%%.*}" # "/path/to/file" (remove all extensions) echo "${filename%.gz}" # "/path/to/file.tar" (remove last extension) ``` ### Arrays ```bash # Indexed arrays declare -a fruits=("apple" "banana" "cherry") fruits+=("date") # Append echo "${fruits[0]}" # "apple" (first element) echo "${fruits[-1]}" # "date" (last element) echo "${fruits[@]}" # All elements echo "${#fruits[@]}" # 4 (length) echo "${!fruits[@]}" # 0 1 2 3 (indices) # Iterate for fruit in "${fruits[@]}"; do echo "$fruit" done # With indices for i in "${!fruits[@]}"; do echo "$i: ${fruits[i]}" done # Associative arrays (bash 4+) declare -A user=( [name]="John" [email]="john@example.com" [age]=30 ) echo "${user[name]}" # "John" echo "${!user[@]}" # Keys: name email age echo "${user[@]}" # Values # Iterate key-value for key in "${!user[@]}"; do echo "$key: ${user[$key]}" done # Array slicing echo "${fruits[@]:1:2}" # "banana" "cherry" (from index 1, 2 elements) # Array filtering (bash 4+) evens=() for n in "${numbers[@]}"; do (( n % 2 == 0 )) && evens+=("$n") done ``` --- ## Control Flow ### Conditionals ```bash # Test operators # Strings [[ -z "$str" ]] # Empty [[ -n "$str" ]] # Not empty [[ "$a" == "$b" ]] # Equal [[ "$a" != "$b" ]] # Not equal [[ "$a" < "$b" ]] # Less than (lexicographic) [[ "$a" =~ ^[0-9]+$ ]] # Regex match # Numbers [[ "$a" -eq "$b" ]] # Equal [[ "$a" -ne "$b" ]] # Not equal [[ "$a" -lt "$b" ]] # Less than [[ "$a" -le "$b" ]] # Less than or equal [[ "$a" -gt "$b" ]] # Greater than [[ "$a" -ge "$b" ]] # Greater than or equal # Files [[ -e "$file" ]] # Exists [[ -f "$file" ]] # Regular file [[ -d "$dir" ]] # Directory [[ -r "$file" ]] # Readable [[ -w "$file" ]] # Writable [[ -x "$file" ]] # Executable [[ -s "$file" ]] # Size > 0 [[ "$a" -nt "$b" ]] # Newer than [[ "$a" -ot "$b" ]] # Older than # If-elif-else if [[ "$status" == "success" ]]; then echo "Success!" elif [[ "$status" == "pending" ]]; then echo "Still pending..." else echo "Failed" fi # Case statement case "$command" in start|begin) start_service ;; stop|end) stop_service ;; restart) stop_service start_service ;; *) echo "Unknown command: $command" exit 1 ;; esac # Short-circuit [[ -f "$file" ]] && process_file "$file" [[ -d "$dir" ]] || mkdir -p "$dir" ``` ### Loops ```bash # For loop for item in item1 item2 item3; do echo "$item" done # C-style for for ((i = 0; i < 10; i++)); do echo "$i" done # While loop counter=0 while [[ $counter -lt 5 ]]; do echo "$counter" ((counter++)) done # Read file line by line while IFS= read -r line; do echo "$line" done < "$file" # Process command output while IFS= read -r file; do echo "Processing: $file" done < <(find . -name "*.txt") # Until loop until [[ -f "$lockfile" ]]; do sleep 1 done # Break and continue for i in {1..10}; do [[ $i -eq 5 ]] && continue [[ $i -eq 8 ]] && break echo "$i" done ``` --- ## Functions ```bash # Basic function greet() { local name="$1" echo "Hello, $name!" } # Function with return value is_valid_email() { local email="$1" [[ "$email" =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$ ]] } # Check return value if is_valid_email "test@example.com"; then echo "Valid email" fi # Function with output capture get_user_count() { wc -l < /etc/passwd } count=$(get_user_count) # Function with array parameter process_files() { local -a files=("$@")
在 GitHub 查看
这个 SKILL.md 很大,SkillsMP 这里只预览前一段内容。 在 GitHub 查看