shell-scripting について
開発者やシステム管理者向けのシェルスクリプトスキルです。Bash と zsh による自動化、エラー処理、CLI ツール開発のパターンを扱います。
主な機能
- 01Bash と zsh のパターン
- 02エラー処理とクリーンアップ
- 03変数、配列、制御フロー
- 04入出力とテキスト処理
- 05シェルスクリプトの実践指針
活用シーン
- 01自動化や定期実行スクリプトの作成
- 02コマンドラインツールの構築
- 03ビルド・デプロイスクリプトの作成
- 04ログや複数ファイルの処理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ 89jobrien/ steve --skill shell-scriptingインストール後、Claude Code で/shell-scriptingを入力して読み込まれたか確認します。
詳細
シェルスクリプト
bash/zsh のパターン、自動化、エラー処理、CLI ツールの開発を網羅したシェルスクリプトのスキルです。
このスキルを使用する場面
- 自動化スクリプトを作成するとき
- CLI ツールを作成するとき
- システム管理タスクを行うとき
- ビルドおよびデプロイのスクリプトを作成するとき
- ログを処理および分析するとき
- ファイル操作や一括処理を行うとき
- cron ジョブやスケジュールされたタスクを設定するとき
スクリプトの構成
テンプレート
#!/usr/bin/env bash
# Script: name.sh
# Description: What this script does
# Usage: ./name.sh [options] <args>
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]}")"
# Default values
VERBOSE=false
DRY_RUN=false
# Functions
usage() {
cat <<EOF
Usage: $SCRIPT_NAME [options] <argument>
Options:
-h, --help Show this help message
-v, --verbose Enable verbose output
-n, --dry-run Show what would be done
EOF
}
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*" >&2
}
error() {
log "ERROR: $*"
exit 1
}
# Main logic
main() {
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
usage
exit 0
;;
-v|--verbose)
VERBOSE=true
shift
;;
-n|--dry-run)
DRY_RUN=true
shift
;;
*)
break
;;
esac
done
# Your logic here
}
main "$@"
エラー処理
オプションの設定
set -e # Exit on any error
set -u # Error on undefined variables
set -o pipefail # Pipe failure is script failure
set -x # Debug: print each command (use sparingly)
クリーンアップ用の trap
cleanup() {
rm -f "$TEMP_FILE"
log "Cleanup complete"
}
trap cleanup EXIT
# Also handle specific signals
trap 'error "Script interrupted"' INT TERM
エラーチェックのパターン
# Check command exists
command -v jq >/dev/null 2>&1 || error "jq is required but not installed"
# Check file exists
[[ -f "$FILE" ]] || error "File not found: $FILE"
# Check directory exists
[[ -d "$DIR" ]] || mkdir -p "$DIR"
# Check variable is set
[[ -n "${VAR:-}" ]] || error "VAR is not set"
# Check exit status explicitly
if ! some_command; then
error "some_command failed"
fi
変数と置換
変数展開
# Default values
${VAR:-default} # Use default if VAR is unset or empty
${VAR:=default} # Set VAR to default if unset or empty
${VAR:+value} # Use value if VAR is set
${VAR:?error msg} # Error if VAR is unset or empty
# String manipulation
${VAR#pattern} # Remove shortest prefix match
${VAR##pattern} # Remove longest prefix match
${VAR%pattern} # Remove shortest suffix match
${VAR%%pattern} # Remove longest suffix match
${VAR/old/new} # Replace first occurrence
${VAR//old/new} # Replace all occurrences
${#VAR} # Length of VAR
配列
# Declare array
declare -a ARRAY=("one" "two" "three")
# Access elements
echo "${ARRAY[0]}" # First element
echo "${ARRAY[@]}" # All elements
echo "${#ARRAY[@]}" # Number of elements
echo "${!ARRAY[@]}" # All indices
# Iterate
for item in "${ARRAY[@]}"; do
echo "$item"
done
# Append
ARRAY+=("four")
連想配列
declare -A MAP
MAP["key1"]="value1"
MAP["key2"]="value2"
# Access
echo "${MAP[key1]}"
# Check key exists
[[ -v MAP[key1] ]] && echo "key1 exists"
# Iterate
for key in "${!MAP[@]}"; do
echo "$key: ${MAP[$key]}"
done
制御フロー
条件分岐
# String comparison
[[ "$str" == "value" ]]
[[ "$str" != "value" ]]
[[ -z "$str" ]] # Empty
[[ -n "$str" ]] # Not empty
# Numeric comparison
[[ "$num" -eq 5 ]] # Equal
[[ "$num" -ne 5 ]] # Not equal
[[ "$num" -lt 5 ]] # Less than
[[ "$num" -gt 5 ]] # Greater than
# File tests
[[ -f "$file" ]] # File exists
[[ -d "$dir" ]] # Directory exists
[[ -r "$file" ]] # Readable
[[ -w "$file" ]] # Writable
[[ -x "$file" ]] # Executable
# Logical operators
[[ "$a" && "$b" ]] # AND
[[ "$a" || "$b" ]] # OR
[[ ! "$a" ]] # NOT
ループ
# For loop
for i in {1..10}; do
echo "$i"
done
# While loop
while read -r line; do
echo "$line"
done < "$file"
# Process substitution
while read -r line; do
echo "$line"
done < <(command)
# C-style for
for ((i=0; i<10; i++)); do
echo "$i"
done
入出力
入力の読み取り
# Read from user
read -r -p "Enter name: " name
# Read password (hidden)
read -r -s -p "Password: " password
# Read with timeout
read -r -t 5 -p "Quick! " answer
# Read file line by line
while IFS= read -r line; do
echo "$line"
done < "$file"
出力とリダイレクト
# Redirect stdout
command > file # Overwrite
command >> file # Append
# Redirect stderr
command 2> file
# Redirect both
command &> file
command > file 2>&1
# Discard output
command > /dev/null 2>&1
# Tee (output and save)
command | tee file
テキスト処理
よく使うパターン
# Find and process files
find . -name "*.log" -exec grep "ERROR" {} +
# Process CSV
while IFS=, read -r col1 col2 col3; do
echo "$col1: $col2"
done < file.csv
# JSON processing (with jq)
jq '.key' file.json
jq -r '.items[]' file.json
# AWK one-liners
awk '{print $1}' file # First column
awk -F: '{print $1}' /etc/passwd # Custom delimiter
awk 'NR > 1' file # Skip header
# SED one-liners
sed 's/old/new/g' file # Replace all
sed -i 's/old/new/g' file # In-place edit
sed -n '10,20p' file # Print lines 10-20
ベストプラクティス
推奨事項
- すべての変数展開を引用符で囲みます:
"$VAR" - テストには
[ ]より[[ ]]を使います - バッククォートより
$(command)を使います - 戻り値を確認します
- 定数には
readonlyを使います - 関数内では
localを使います --helpオプションを用意します- 意味のある終了コードを使います
避けるべきこと
lsの出力を解析すること- 信頼できない入力に
evalを使うこと - パスに空白が含まれないと仮定すること
- shellcheck の警告を無視すること
- 1つの巨大なスクリプトを書くこと(モジュール化します)
参考ファイル
references/one_liners.md- 便利なワンライナーコマンド
他のスキルとの連携
- developer-experience - ツールの自動化に使用します
- debugging - スクリプトのデバッグに使用します
- testing - スクリプトのテストパターンに使用します
コメント
Markdown 対応