Bashスクリプトを作成していると、実行時に「-h(ヘルプ)」「-v(詳細出力)」「-f [ファイル名]」といったオプション引数を渡して動作を制御したくなることがあります。
単純に $1 や $2 といった位置パラメータで引数を受け取ることも可能ですが、引数の順番を間違えたり、オプションの数が多くなったりすると、スクリプトの保守性が著しく低下します。
そこで活躍するのが、Bashの組み込みコマンドである getopts です。本記事では、getopts を使って本格的なCLIツールのようなオプション引数を実装する方法と、そのベストプラクティスを解説します。
1. getoptsの基本構文と動作原理
getopts は、スクリプトに渡されたオプション引数(-a, -b, -c など)を1つずつ順番に解析し、変数に格納するコマンドです。通常は while ループと組み合わせて使用します。
#!/bin/bash
# 使用可能なオプション文字を文字列として指定する
# 例:"ab:c" は、-a, -b (引数あり), -c の3つのオプションを受け付ける
while getopts "ab:c" opt; do
case "$opt" in
a)
echo "オプション -a が指定されました"
;;
b)
# コロン(:)が付いたオプションは、直後の引数を $OPTARG に格納する
echo "オプション -b が指定されました。引数は: $OPTARG"
;;
c)
echo "オプション -c が指定されました"
;;
\?)
# 未定義のオプションが指定された場合の処理
echo "無効なオプションです: -$OPTARG" >&2
exit 1
;;
esac
doneオプション文字列のルール
getopts の第1引数に指定する文字列(上記の例では "ab:c")には、スクリプトが受け付けるオプション文字を並べます。
- 単一の文字(例:
a):引数を取らないオプション(フラグ)を表します。 - 文字の後にコロン(例:
b:):引数を取るオプションを表します。この場合、指定された引数の値は$OPTARGという特別な変数に格納されます。
2. 実用的なスクリプトのテンプレート(型)
実務でそのまま使える、ヘルプ表示(-h)やファイル指定(-f)、詳細出力(-v)を備えたスクリプトのテンプレートを紹介します。
#!/bin/bash
# デフォルト値の設定
VERBOSE=false
TARGET_FILE=""
# ヘルプメッセージを表示する関数
show_help() {
echo "Usage: $(basename "$0") [-h] [-v] [-f FILE]"
echo "Options:"
echo " -h Show this help message and exit"
echo " -v Enable verbose output"
echo " -f FILE Specify the target file (required)"
exit 0
}
# getopts によるオプション解析
# 先頭にコロン(:)を付けると、getopts が独自のエラーメッセージを出力しなくなる(サイレントエラーハンドリング)
while getopts ":hvf:" opt; do
case "$opt" in
h)
show_help
;;
v)
VERBOSE=true
;;
f)
TARGET_FILE="$OPTARG"
;;
\?)
echo "Error: Invalid option -$OPTARG" >&2
show_help
;;
:)
# 引数が必須のオプションに引数が渡されなかった場合の処理
echo "Error: Option -$OPTARG requires an argument." >&2
show_help
;;
esac
done
# getopts で解析したオプション分だけ、位置パラメータ($1, $2...)をシフト(削除)する
# これにより、オプション以外の残りの引数(ファイル名など)を正しく処理できる
shift $((OPTIND - 1))
# 必須オプションのチェック
if [[ -z "$TARGET_FILE" ]]; then
echo "Error: -f option is required." >&2
show_help
fi
# メイン処理
if $VERBOSE; then
echo "Starting process..."
echo "Target file: $TARGET_FILE"
fi
# ここに実際の処理を記述する
# echo "Processing $TARGET_FILE..."重要なポイント解説
- 先頭のコロン(
:hvf:):オプション文字列の先頭に:を付けると、getoptsはエラーメッセージ(「無効なオプション」や「引数不足」)を標準エラー出力に自動で表示しなくなります。代わりに、スクリプト内で独自のエラーメッセージ(\?や:のケース)を定義して、より親切なエラーハンドリングを行うことができます。 - 引数不足の検知(
:):-fのように引数が必要なオプションに対して、ユーザーが引数を指定しなかった場合、getoptsは$optに:をセットし、$OPTARGにそのオプション文字(この場合はf)を格納します。 shift $((OPTIND - 1)):OPTINDは、getoptsが次に処理すべき引数のインデックス(位置)を保持する変数です。オプションの解析が終わった後、shiftコマンドを使って、解析済みのオプション引数を取り除きます。これにより、オプション以外の引数(例えばscript.sh -v -f data.txt arg1 arg2のarg1 arg2)を$1,$2として簡単に取得できるようになります。
3. getoptsの制限事項と代替手段
getopts は非常に便利ですが、ロングオプション(例:--help, --file)には対応していないという制限があります。
もしロングオプションを実装したい場合は、getopts ではなく、外部コマンドである getopt(末尾の “s” がない)を使用するか、手動で while ループと case 文を使って引数を解析する必要があります。しかし、Bashの組み込み機能だけで完結し、環境に依存せずに動作する getopts は、多くのシェルスクリプトにおいて最初の選択肢となるべき強力なツールです。
まとめ
getopts をマスターすれば、あなたのシェルスクリプトは単なる「自動化の羅列」から、誰が使っても分かりやすく、堅牢な「CLIツール」へと進化します。
- オプション文字とコロン(
:)で受け付けるオプションを定義する。 whileループとcase文で解析し、変数にフラグや値を格納する。- 必須オプションのチェックやヘルプメッセージの実装を組み合わせる。
このテンプレートをスニペットとして登録し、新しいスクリプトを作成する際の土台として活用してください。
