シェルスクリプトにおいて、実行時に外部から値を渡すことは頻繁に行われる基本操作です。この仕組みにより、スクリプトの挙動を実行時に入力に応じて動的に制御できます。本稿では、位置パラメータの取り扱い、検証、および安全な利用方法について解説します。
1. 位置パラメータの構造
スクリプト起動時にスペース区切りで指定された文字列は、自動的に位置パラメータとして割り当てられます。たとえば、./deploy.sh prod /var/www/html を実行した場合、prod が第1引数($1)、/var/www/html が第2引数($2)になります。
主な特殊変数:
$0:実行中のスクリプトファイル名(パス付き)$1~$9:1〜9番目の引数(10以降は${10}のように中括弧必須)$#:引数の総数$@:各引数を個別にクォートされた状態で展開("$1" "$2" ...)$*:すべての引数を単一の文字列として展開("$1 $2 ...")
2. 実践的な引数利用例
以下は、環境名と出力先パスを受け取り、ログディレクトリを生成するスクリプトです:
#!/bin/bash
# 引数が2つあるか確認
if [[ $# -lt 2 ]]; then
echo "エラー: 環境名と出力パスを指定してください。"
echo "使用例: $0 staging /tmp/logs"
exit 2
fi
ENV_NAME="$1"
OUTPUT_PATH="$2"
# セーフなパス展開(空白・特殊文字対応)
mkdir -p "$OUTPUT_PATH/$ENV_NAME"
echo "ディレクトリ作成完了: $OUTPUT_PATH/$ENV_NAME"
実行結果例:
./setup.sh dev "/home/user/app logs" → /home/user/app logs/dev が作成されます。
3. 安全な引数処理のポイント
- クォートの徹底:変数展開時は必ずダブルクォートで囲む(例:
"$1")。未クォートの$1はワード分割・グロブ展開を引き起こす危険があります。 - 引数の存在チェック:必須引数は
[[ -z "$1" ]]や[[ $# -eq 0 ]]で事前に検証。 - shiftによる逐次処理:複数オプションを順次処理したい場合、
shiftで引数リストを左シフト可能($1が消え、$2→$1に移動)。
4. 複数引数のバッチ処理
以下は、任意数のファイルパスを受け取り、それぞれのサイズを表示するスクリプトです:
#!/bin/bash
if [[ $# -eq 0 ]]; then
echo "ファイルパスを1つ以上指定してください。"
exit 1
fi
for file_path in "$@"; do
if [[ -f "$file_path" ]]; then
size_bytes=$(stat -c "%s" "$file_path" 2>/dev/null)
echo "[$file_path] → $(numfmt --to=iec-i "$size_bytes")"
else
echo "警告: '$file_path' は存在しません。"
fi
done
この例では"$@"を使い、各引数を独立して安全に反復処理しています。