Bashスクリプトにオプション引数を実装する:getoptsを使った本格的なツール作成法

データとパラメータ展開

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..."

重要なポイント解説

  1. 先頭のコロン(:hvf::オプション文字列の先頭に : を付けると、getopts はエラーメッセージ(「無効なオプション」や「引数不足」)を標準エラー出力に自動で表示しなくなります。代わりに、スクリプト内で独自のエラーメッセージ(\?: のケース)を定義して、より親切なエラーハンドリングを行うことができます。
  2. 引数不足の検知(:-f のように引数が必要なオプションに対して、ユーザーが引数を指定しなかった場合、getopts$opt: をセットし、$OPTARG にそのオプション文字(この場合は f)を格納します。
  3. shift $((OPTIND - 1))OPTIND は、getopts が次に処理すべき引数のインデックス(位置)を保持する変数です。オプションの解析が終わった後、shift コマンドを使って、解析済みのオプション引数を取り除きます。これにより、オプション以外の引数(例えば script.sh -v -f data.txt arg1 arg2arg1 arg2)を $1, $2 として簡単に取得できるようになります。

3. getoptsの制限事項と代替手段

getopts は非常に便利ですが、ロングオプション(例:--help, --file)には対応していないという制限があります。

もしロングオプションを実装したい場合は、getopts ではなく、外部コマンドである getopt(末尾の “s” がない)を使用するか、手動で while ループと case 文を使って引数を解析する必要があります。しかし、Bashの組み込み機能だけで完結し、環境に依存せずに動作する getopts は、多くのシェルスクリプトにおいて最初の選択肢となるべき強力なツールです。

まとめ

getopts をマスターすれば、あなたのシェルスクリプトは単なる「自動化の羅列」から、誰が使っても分かりやすく、堅牢な「CLIツール」へと進化します。

  1. オプション文字とコロン(:)で受け付けるオプションを定義する。
  2. while ループと case 文で解析し、変数にフラグや値を格納する。
  3. 必須オプションのチェックやヘルプメッセージの実装を組み合わせる。

このテンプレートをスニペットとして登録し、新しいスクリプトを作成する際の土台として活用してください。

Bash玄

はじめまして!Bash玄です。

エンジニアとしてシステム運用に携わる中で、手作業の多さに限界を感じ、Bashスクリプトを活用して業務を効率化したのがきっかけで、この道に入りました。「手作業は負け」「スクリプトはシンプルに」をモットーに、誰でも実践できるBashスクリプトの書き方を発信しています。

このサイトでは、Bashの基礎から実践的なスクリプト作成まで、初心者でもわかりやすく解説しています。少しでも「Bashって便利だな」と思ってもらえたら嬉しいです!

# 好きなこと
- シンプルなコードを書くこと
- コマンドラインを快適にカスタマイズすること
- 自動化で時間を生み出すこと

# このサイトを読んでほしい人
- Bashに興味があるけど、何から始めればいいかわからない人
- 定型業務を自動化したい人
- 効率よくターミナルを使いこなしたい人

Bashの世界に一歩踏み出して、一緒に「Bash道」を極めていきましょう!

Bash玄をフォローする