シェルスクリプトにbash補完を追加する設計|complete・compgenで独自コマンドのタブ補完を実装する方法

運営:リナックスマスター.JP(代表 宮崎智広)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > シェルスクリプト > シェルスクリプトにbash補完を追加する設計|complete・compgenで独自コマンドのタブ補完を実装する方法
「自分で作ったシェルスクリプトにオプションが増えてきた。--dry-run や --verbose を毎回手入力するのは面倒だし、タイポも多い」
「git や systemctl はタブキーで補完できるのに、自作スクリプトはそれができない。同じことができるようにしたい」

この差を生み出しているのが bash の補完機能だ。complete コマンドと compgen コマンドを使えば、自作スクリプトにも同じ仕組みを追加できる。

この記事では、RHEL 9系/Ubuntu 24.04 LTS を想定環境として、bash 補完スクリプトの設計方法を解説します。固定オプション一覧の登録から、サブコマンドごとに候補を変える動的補完、/etc/bash_completion.d/ への永続化まで順を追って説明します。

この記事のポイント

・complete -W でオプション一覧を登録すれば自作スクリプトがタブ補完できる
・compgen でファイル名・コマンド名・任意リストを動的生成できる
・補完関数(_関数)でサブコマンドごとに候補を切り替えられる
・/etc/bash_completion.d/ に置けば起動時に自動読み込みされる


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

bash補完の仕組みと complete コマンドの役割

bash がタブキーを押した時に候補を出す仕組みは、内部で管理している「コマンド名→補完方法」というマッピングで動いている。git や systemctl の補完定義は /etc/bash_completion.d/ 配下のスクリプトが起動時に登録している。自作スクリプトはこのマッピングに何も登録されていないため、タブを押しても候補が出ない。

この登録を行うコマンドが complete だ。

# complete コマンドの基本構文 complete [オプション] コマンド名 # 現在登録済みの補完定義を一覧確認する complete -p # 特定コマンドの補完定義だけ確認する complete -p git # 出力例(環境により異なります) # complete -o bashdefault -o default -o nospace -F __git_wrap__git_main git

complete -p で大量の定義が見られるはずだ。自作スクリプトをここに追加するのがこの記事の目的になる。

静的な補完候補リストを登録する

最もシンプルな補完は、オプション一覧を固定テキストで登録する方法だ。

1. サンプルスクリプトのオプションを整理する

例として、以下のオプションを受け付けるデプロイスクリプト deploy.sh を想定する。

# deploy.sh が受け付けるオプション --production --staging --dry-run --verbose --help

2. complete -W で候補リストを登録する

# ターミナルで直接実行して試す(現在のセッションのみ有効) complete -W "--production --staging --dry-run --verbose --help" deploy.sh # 登録後、以下のように入力してタブを押すと候補が表示される # deploy.sh --[Tab] # 出力例(環境により異なります) # --dry-run --help --production --staging --verbose

complete -W の文字列にスペース区切りでオプションを並べるだけだ。前方一致でも絞り込まれる。deploy.sh --p[Tab] なら --production だけが候補になる。

ただし、この方法は現在のシェルセッションにしか有効でない。シェルを閉じると消える。永続化の方法は後述する。

compgen で動的な補完候補を生成する

引数にファイル名を取る・ユーザー名を入力させる・状況によって候補を変えたい場合は compgen が使いやすい。compgen は補完候補のリストを標準出力に書き出すコマンドで、complete と組み合わせて動的な補完を実現する。

主なオプションは以下の通りだ。

・-W "word1 word2":指定した単語リストを候補にする
・-f:カレントディレクトリのファイル名を候補にする
・-d:ディレクトリ名のみを候補にする
・-c:PATH 上の実行可能コマンド名を候補にする
・-u:システムのユーザー名を候補にする

# compgen の動作確認(ターミナルで直接実行して試す) # "b" で始まる単語を候補リストから絞り込む compgen -W "--backup --build --break" -- "--b" # 出力例(環境により異なります) # --backup # --build # ファイル名一覧を生成する compgen -f -- "/" # 出力例(環境により異なります) # /bin # /boot # /etc ... # ディレクトリ名だけを補完させる complete -A directory restore.sh

補完関数(_関数)でサブコマンド補完を実装する

オプションが複数レベルになるスクリプト(backup.sh start、backup.sh full-backup /srv/data のようにサブコマンドで動作が変わるもの)は、補完関数を使うと柔軟に対応できる。

bash 補完では _コマンド名 という名前の関数を定義し、それを -F オプションで complete に登録するのが慣例だ。関数内では以下の特殊変数を参照する。

・COMP_WORDS:現在の入力を単語単位で分割した配列
・COMP_CWORD:カーソル位置の単語インデックス(0 がコマンド名)
・COMPREPLY:補完候補を格納する配列(この配列に入れた値がタブ補完で表示される)

シェルスクリプトの設計パターンを体系的に学びたい場合は、シェルスクリプト実践講座でbash補完を含む設計の全体像を確認できる。

1. 補完スクリプトを書く

#!/usr/bin/env bash # /etc/bash_completion.d/backup の内容 _backup_sh() { local cur prev cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" local subcommands="start stop status full-backup incremental-backup" case "$prev" in backup.sh) # サブコマンドの一覧を補完する COMPREPLY=( $(compgen -W "$subcommands" -- "$cur") ) ;; full-backup|incremental-backup) # バックアップ先のディレクトリを補完する COMPREPLY=( $(compgen -d -- "$cur") ) ;; start|stop|status) # これらのサブコマンドはオプションなし COMPREPLY=() ;; *) COMPREPLY=() ;; esac } complete -F _backup_sh backup.sh

2. 動作を確認する

# スクリプトを現在のシェルに読み込む source /etc/bash_completion.d/backup # backup.sh の後でタブを押すとサブコマンドが候補に出る # backup.sh [Tab] # 出力例(環境により異なります) # full-backup incremental-backup start status stop # full-backup の後でタブを押すとディレクトリ補完になる # backup.sh full-backup /[Tab] # 出力例(環境により異なります) # /boot/ /etc/ /home/ /srv/ /var/

COMP_CWORD の値は入力している単語位置のインデックスだ。backup.sh full-backup /s と入力している場合は COMP_CWORD=2 になり、prev には full-backup が入る。この値で case 文を分岐させ、候補を切り替えている。

/etc/bash_completion.d/ に配置して永続化する

補完定義をシェルを閉じても維持するには、/etc/bash_completion.d/ への配置が標準的な方法だ。bash 起動時に bash_completion パッケージがこのディレクトリ配下のファイルを自動読み込みする。

1. bash-completion パッケージを確認する

# RHEL 9系の場合 rpm -q bash-completion # Ubuntu 24.04 LTS の場合 dpkg -l bash-completion # インストールされていない場合 # RHEL 9系 sudo dnf install bash-completion # Ubuntu 24.04 LTS sudo apt install bash-completion

2. 補完スクリプトを配置する

# システム全体(全ユーザーが使えるようにする) sudo cp backup_completion.sh /etc/bash_completion.d/backup sudo chmod 644 /etc/bash_completion.d/backup # 自分のユーザーだけに適用したい場合は ~/.bash_completion を使う # tee -a で追記する(ファイルが存在しない場合は新規作成される) echo "source /path/to/backup_completion.sh" | tee -a ~/.bash_completion

ファイル名に拡張子 .sh は不要だ(backup でよい)。拡張子があっても動作に支障はないが、/etc/bash_completion.d/ 配下の慣例では拡張子なしが多い。

3. 新しいシェルセッションで確認する

# 現在のセッションに反映させる(新規ターミナルを開いてもよい) source /etc/bash_completion # 補完が登録されているか確認する complete -p backup.sh # 出力例(環境により異なります) # complete -F _backup_sh backup.sh

補完が効かない時のトラブルシュート

補完スクリプトを配置したのに動かない場合の確認手順を整理する。

1. bash_completion が読み込まれているか確認する

# bash_completion の読み込みを確認する type _completion_loader 2>&1 # 読み込まれている場合の出力例(環境により異なります) # _completion_loader is a function # 出力が "bash: type: _completion_loader: not found" の場合は # ~/.bashrc や /etc/bashrc に以下の記述があるか確認する grep bash_completion ~/.bashrc /etc/bashrc 2>/dev/null

_completion_loader が存在しない場合、bash_completion が起動時に読み込まれていない。~/.bashrc に source /etc/bash_completion の行を追加して解決できる。

2. complete -p で補完定義の登録状況を確認する

# 特定スクリプトの補完定義を確認する complete -p backup.sh 2>&1 # 登録されていない場合の出力例(環境により異なります) # -bash: complete: backup.sh: no completion specification

「no completion specification」が出た場合、補完スクリプトの読み込みに失敗している可能性が高い。

3. スクリプトを手動で読み込んで構文エラーを確認する

# 手動で読み込んでエラーメッセージを確認する source /etc/bash_completion.d/backup # bash -n で構文チェックだけ行う(実行しない) bash -n /etc/bash_completion.d/backup # エラーがなければ何も出力されない # エラーがある場合の出力例(環境により異なります) # /etc/bash_completion.d/backup: line 12: syntax error near unexpected token `fi'

bash -n でエラーが出た場合、スクリプト内の構文ミス(fi や esac の閉じ忘れ等)が原因だ。shellcheck /etc/bash_completion.d/backup で静的解析をかけると原因箇所を特定しやすい。

本記事のまとめ

bash 補完を自作シェルスクリプトに追加する方法をまとめる。
やりたいこと 方法
固定オプション一覧を補完させる complete -W "--opt1 --opt2" script.sh
ファイル名を補完させる complete -A file script.sh
ディレクトリ名だけ補完させる complete -A directory script.sh
入力途中で候補を絞り込む compgen -W "list" -- "$cur" を COMPREPLY に格納
サブコマンドで候補を変える complete -F _関数名 script.sh で補完関数を登録
全ユーザーで永続化する /etc/bash_completion.d/ に配置(chmod 644)
自分のユーザーのみに適用する ~/.bash_completion に source 行を追加
補完定義の登録状況を確認する complete -p script.sh
スクリプトが小さいうちは complete -W の静的リストで十分だ。オプションが増えてきたり、サブコマンドが加わったりしたら -F _関数名 形式に切り替えると、現在の入力状況に応じた動的な補完が実現できる。補完スクリプト自体も通常の bash スクリプトなので、shellcheck での静的解析を習慣にすると品質を保ちやすい。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、bash補完設計を含むシェルスクリプトの設計パターンをシェルスクリプト実践講座で体系的に学べます。complete・compgen の使い方から、実務で壊れないスクリプト設計まで現役エンジニアが解説しています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録

運営

リナックスマスター.JP(代表 宮崎智広)

株式会社イーネットマーキュリーが運営するLinux教育サイトです。代表の宮崎智広は現役のLinuxサーバー管理者として20年以上の実務経験を持ち、累計3,100名以上のエンジニアを指導してきました。実践型のLinuxセミナーや無料マニュアルの配布を通じてLinux人材の育成に取り組んでいます。