UNIX系の多機能インタラクティブシェルで特徴的なのが強力な補完機能だ。最近はPowerShellでも補完機能が使えるようになったが、それでもbashのようなUNIX系の多機能インタラクティブシェルのほうがまだ一枚上手かなという気がする(fish辺りまで来ると、補完機能が文脈を加味するようになるのでさらに便利になる)。今回は、bashで補完機能を使うためのショートカットキーを取り上げる。
補完に関するショートカットキー
今回も「bind -p」の出力結果を整理するところから始めよう。「bind -p」の出力を整理したものは稿末に付録として添付しておくので、詳しくはそちらを参照していただきたい。「bind -p」の出力から補完に関するものを取り出して整理すると、補完に関する機能としては次のキーがデフォルトで設定されている。
| キー | 操作 |
|---|---|
| 「Tab」 | 補完 |
| 「ESC」「ESC」 | 補完 |
| 「ESC」「!」 | コマンド名を補完 |
| 「ESC」「/」 | ファイル名を補完 |
| 「ESC」「@」 | ホスト名を補完 |
| 「ESC」「{」 | 補完対象をブレース展開表記へ補完 |
| 「ESC」「~」 | ユーザ名を補完 |
| 「ESC」「$」 | 変数名を補完 |
「Tab」キーと「ESC」「ESC」は同じものだ。「Tab」キーと「Ctrl」+「i」は同じキーになるので、「Tab」キーと「ESC」「ESC」と「Ctrl」+「i」は同じ、と言うこともできる。
最初に今回の結論を書いておくと、補完としては「Tab」キーだけ覚えておけばよい。「Tab」キーはそれ以外の「○○を補完」の全てを自動的に行うものだと考えてもらえればよいと思う。とりあえず「Tab」キーを押せば何かが補完される。これだけ覚えておけば、結構使えるので便利だ。
それ以外の「ESC」「記号」というショートカットキーは、補完対象がそれぞれ限定されている。つまり、「Tab」キーで自動的に補完するのではなく、明示的に自分で補完対象を指定したい場合には「ESC」「記号」というショートカットキーを使えばよいということになる。
しかし、「ESC」「記号」はそれほど便利なショートカットキーとは言えない。「ESC」「記号」で使うショートカットキーで実際にどのキーが押されることになるのか、以下をご覧いただきたい。
押すキーの組み合わせを表に整理すると次のようになる。
| 操作 | 日本語キーボード | 英語キーボード |
|---|---|---|
| コマンド名を補完 | 「ESC」「Shift」+「1」 | 「ESC」「Shift」+「1」 |
| ファイル名を補完 | 「ESC」「/」 | 「ESC」「/」 |
| ホスト名を補完 | 「ESC」「@」 | 「ESC」「Shift」+「@」 |
| 補完対象をブレース展開表記へ補完 | 「ESC」「Shift」+「[」 | 「ESC」「Shift」+「[」 |
| ユーザ名を補完 | 「ESC」「Shift」+「^」 | 「ESC」「Shift」+「`」 |
| 変数名を補完 | 「ESC」「Shift」+「4」 | 「ESC」「Shift」+「4」 |
記号を入力するために「Shift」キーを押したり押さなかったりと、ばらばらなのだ。補完に使う記号が1カ所にまとまっていることもなく、散在している。この補完機能は覚えるのに苦労するわりに、得られるメリットが小さい。
それでも「ESC」「記号」を覚えるなら
それでも「ESC」「記号」のショートカットキーを覚えるなら、いくつかはこじつけとなるが、記号と補完対象を次のように紐付けて覚えておくといいかもしれない。漫然と記号を暗記するのよりは覚えやすいのではないだろうか。
| 操作 | 記号 | こじつけ意味 |
|---|---|---|
| コマンド名を補完 | ! | コマンド履歴からコマンドを実行するときに「!」を使うので、そこから転じてコマンド名の補完 |
| ファイル名を補完 | / | パスには区切り文字「/」が含まれるので、そこから転じてファイル名 |
| ホスト名を補完 | @ | ホスト名は「@ホスト名」のように表記されることもあるので、そこから転じてホスト名 |
| 補完対象をブレース展開表記へ補完 | { | ブレース展開が{a,b}のようにそのまま波括弧を使って書くので、そこから転じてブレース展開 |
| ユーザ名を補完 | ~ | 「~」はホームディレクトリを意味しており、ホームディレクトリパスにはユーザー名が含まれることが多いので、そこから転じてユーザー名 |
| 変数名を補完 | $ | 変数は「$」から記述するので、そこから転じて変数名 |
使い方は簡単で、補完機能を使いたいタイミングでそのキーを入力すればよい。何も入力していない段階でショートカッキーを押して補完候補を全て表示させたい場合には、ショートカットキーを2回連続して入力すれば表示される。
今回取り上げたのは結局「Tab」キーだけということになるが、これだけでも十分価値のある機能だ。もちろん、手癖として「ESC」「ESC」のほうが好きという場合にはそちらでもよいと思う。「ESC」「ESC」のほうを癖にしておくと「ESC」「記号」という入力と整合性が取れやすいので、こちらも活用するなら「ESC」「ESC」を覚えるというのは結構合理的な選択だ。
付録 bashのお薦めショートカットキー
| キー | 操作 |
|---|---|
| 「→」 | カーソルを1文字右へ移動。 |
| 「←」 | カーソルを1文字左へ移動。 |
| 「Home」 | カーソルを行頭へ移動。 |
| 「End」 | カーソルを行末へ移動。 |
| 「Ctrl」+「→」 | カーソルを単語の末尾へ移動、すでに単語の末尾の場合は、次の単語の末尾へ移動。 |
| 「Ctrl」+「←」 | カーソルを単語の先頭へ移動、すでに単語の先頭の場合は、前の単語の先頭へ移動。 |
| キー | 機能 |
|---|---|
| 「Backspace」 | カーソルのひとつ左の文字を削除。 |
| 「Delete」 | カーソルのある場所の文字を削除。 |
| 「Ctrl」+「Backspace」 | カーソルのひとつ左の文字から単語頭までを削除。 |
| 「Ctrl」+「Delete」 | カーソルから単語末までを削除。 |
| 「Ctrl」+「Home」 | カーソルのひとつ左の文字から行頭までを削除。 |
| 「Ctrl」+「End」 | カーソルから行末までを削除。 |
上記操作に操作に必要な設定
"\C-h": backward-kill-word # Ctrl-Backspace
"\e[1;5H": unix-line-discard # Ctrl-Home
"\e[1;5F": kill-line # Ctrl-End
| キー | 機能 |
|---|---|
| 「Backspace」 | カーソルのひとつ左の文字を削除。 |
| 「Delete」 | カーソルのある場所の文字を削除。 |
| 「ESC」「Backspace」 | カーソルのひとつ左の文字から単語頭までを削除。 |
| 「ESC」「Delete」 | カーソルから単語末までを削除。 |
| 「Ctrl」+「u」 | カーソルのひとつ左の文字から行頭までを削除。 |
| 「Ctrl」+「k」 | カーソルから行末までを削除。 |
上記操作に操作に必要な設定
"\e\e[3~": kill-word # ESC Delete
| キー | 操作 |
|---|---|
| 「↑」 | コマンド履歴からひとつ前のコマンドを表示(古い方へ)。 |
| 「↓」 | コマンド履歴からひとつ後のコマンドを表示(新しい方へ)。 |
| 「Ctrl」+「r」 | インクリメンタルコマンド履歴検索(古い方へ)。 |
| 「Ctrl」+「s」 | インクリメンタルコマンド履歴検索(新しい方へ)。 |
| キー | 操作 |
|---|---|
| 「Tab」 | 補完 |
付録 Windows Terminal キーとキー表記
| キー | キー表記 |
|---|---|
| 「ESC」 | \e |
| 「ESC」「ESC」 | \e\e |
| 「Home」 | \e[H |
| 「Insert」 | \e[2~ |
| 「Delete」 | \e[3~ |
| 「End」 | \e[F |
| 「Page Up」 | \e[5~ |
| 「Page Down」 | \e[6~ |
| 「F1」 | \eOP |
| 「F2」 | \eOQ |
| 「F3」 | \eOR |
| 「F4」 | \eOS |
| 「F5」 | \eO15~ |
| 「F6」 | \eO17~ |
| 「F7」 | \eO18~ |
| 「F8」 | \eO19~ |
| 「F9」 | \eO20~ |
| 「F10」 | \eO21~ |
| 「Alt」+「Home」 | \e[1;3H |
| 「Alt」+「Insert」 | \e[2;3~ |
| 「Alt」+「Delete」 | \e[3;3~ |
| 「Alt」+「End」 | \e[1;3F |
| 「Alt」+「Page Up」 | \e[5;3~ |
| 「Alt」+「Page Down」 | \e[6;3~ |
| 「Ctrl」+「Home」 | \e[1;5H |
| 「Ctrl」+「Insert」 | \e[2;5~ |
| 「Ctrl」+「Delete」 | \e[3;5~ |
| 「Ctrl」+「End」 | \e[1;5F |
| 「Ctrl」+「Page Up」 | \e[5;5~ |
| 「Ctrl」+「Page Down」 | \e[6;5~ |
| 「↑」 | \e[A |
| 「↓」 | \e[B |
| 「→」 | \e[C |
| 「←」 | \e[D |
| 「Alt」+「↑」 | \e[1;3A |
| 「Alt」+「↓」 | \e[1;3B |
| 「Alt」+「→」 | \e[1;3C |
| 「Alt」+「←」 | \e[1;3D |
| 「Ctrl」+「↑」 | \e[1;5A |
| 「Ctrl」+「↓」 | \e[1;5B |
| 「Ctrl」+「→」 | \e[1;5C |
| 「Ctrl」+「←」 | \e[1;5D |
| 貼り付け開始 | \e[200~ |
| クエリステータスレポート | \e[5n |
| クエリステータスレポート(応答) | \e[0n |
| 「Backspace」 | \C-? |
| 「Ctrl」+「Backspace」 | \C-H |
| 「Tab」 | \C-I |
| 「Enter」 | \C-M |
付録 Mac Terminal キーとキー表記
| キー | キー表記 |
|---|---|
| 「ESC」 | \e |
| 「ESC」「ESC」 | \e\e |
| 「Home」 | なし |
| 「Insert」 | なし |
| 「Delete」 | \e[3~ |
| 「End」 | なし |
| 「Page Up」 | なし |
| 「Page Down」 | なし |
| 「F1」 | \eOP |
| 「F2」 | \eOQ |
| 「F3」 | \eOR |
| 「F4」 | \eOS |
| 「F5」 | \eO15~ |
| 「F6」 | \eO17~ |
| 「F7」 | \eO18~ |
| 「F8」 | \eO19~ |
| 「F9」 | \eO20~ |
| 「F10」 | なし |
| 「F11」 | \eO23~ |
| 「F12」 | \eO24~ |
| 「Alt」+「Home」 | なし |
| 「Alt」+「Insert」 | なし |
| 「Alt」+「Delete」 | なし |
| 「Alt」+「End」 | なし |
| 「Alt」+「Page Up」 | なし |
| 「Alt」+「Page Down」 | なし |
| 「Ctrl」+「Home」 | なし |
| 「Ctrl」+「Insert」 | なし |
| 「Ctrl」+「Delete」 | \e[3;5~ |
| 「Ctrl」+「End」 | なし |
| 「Ctrl」+「Page Up」 | なし |
| 「Ctrl」+「Page Down」 | なし |
| 「↑」 | \e[A |
| 「↓」 | \e[B |
| 「→」 | \e[C |
| 「←」 | \e[D |
| 「Alt」+「↑」 | なし |
| 「Alt」+「↓」 | なし |
| 「Alt」+「→」 | なし |
| 「Alt」+「←」 | なし |
| 「Ctrl」+「↑」 | \e[A |
| 「Ctrl」+「↓」 | \e[B |
| 「Ctrl」+「→」 | \e[1;5C |
| 「Ctrl」+「←」 | \e[1;5D |
| 貼り付け開始 | \e[200~ |
| クエリステータスレポート | \e[5n |
| クエリステータスレポート(応答) | \e[0n |
| 「Backspace」 | \C-H |
| 「Ctrl」+「Backspace」 | \C-H |
| 「Tab」 | \C-I |
| 「Enter」 | \C-M |
付録 bash bind -p 出力キー対応表
| キー表記 | キー | readline関数(Ubuntu 20.04デフォルト割当) |
|---|---|---|
| \e | 「ESC」 | set-mark |
| \C-g | 「Ctrl」+「g」 | abort |
| \C-x\C-g | 「Ctrl」+「x」「Ctrl」+「g」 | abort |
| \e\C-g | 「ESC」「Ctrl」+「g」 | abort |
| \C-j | 「Enter」 | accept-line |
| \C-m | 「Enter」 | accept-line |
| \C-b | 「Ctrl」+「b」 | backward-char |
| \eOD | 「←」 | backward-char |
| \e[D | 「←」 | backward-char |
| \C-? | 「Backspace」 | backward-delete-char |
| \C-h | 「Ctrl」+「Backspace」 | backward-delete-char |
| \C-x\C-? | 「Ctrl」+「x」「Ctrl」+「Backspace」 | backward-kill-line |
| \e\C-? | 「ESC」「Ctrl」+「Backspace」 | backward-kill-word |
| \e\C-h | 「ESC」「Backspace」 | backward-kill-word |
| \e[1;3D | 「Alt」+「←」 | backward-word |
| \e[1;5D | 「Ctrl」+「←」 | backward-word |
| \e[5D | 「Ctrl」+「←」 | backward-word |
| \e\e[D | 「ESC」「←」 | backward-word |
| \eb | 「ESC」「b」 | backward-word |
| \e< | 「ESC」「<」 | beginning-of-history |
| \C-a | 「Ctrl」+「a」 | beginning-of-line |
| \eOH | 「Home」 | beginning-of-line |
| \e[1~ | 「Home」 | beginning-of-line |
| \e[H | 「Home」 | beginning-of-line |
| \e[200~ | 貼り付け開始 | bracketed-paste-begin |
| \C-xe | 「Ctrl」+「x」「e」 | call-last-kbd-macro |
| \C-] | 「Ctrl」+「]」 | character-search |
| \e\C-] | 「ESC」「Ctrl」+「]」 | character-search-backward |
| \C-l | 「Ctrl」+「l」 | clear-screen |
| \C-i | 「Tab」 | complete |
| \e\e | 「ESC」「ESC」 | complete |
| \e! | 「ESC」「!」 | complete-command |
| \e/ | 「ESC」「/」 | complete-filename |
| \e@ | 「ESC」「@」 | complete-hostname |
| \e{ | 「ESC」「{」 | complete-into-braces |
| \e~ | 「ESC」「~」 | complete-username |
| \e$ | 「ESC」「$」 | complete-variable |
| \C-d | 「Ctrl」+「d」 | delete-char |
| \e[3~ | 「Delete」 | delete-char |
| \e\ | 「ESC」「\」 | delete-horizontal-space |
| \e- | 「ESC」「-」 | digit-argument |
| \e0 | 「ESC」「0」 | digit-argument |
| \e1 | 「ESC」「1」 | digit-argument |
| \e2 | 「ESC」「2」 | digit-argument |
| \e3 | 「ESC」「3」 | digit-argument |
| \e4 | 「ESC」「4」 | digit-argument |
| \e5 | 「ESC」「5」 | digit-argument |
| \e6 | 「ESC」「6」 | digit-argument |
| \e7 | 「ESC」「7」 | digit-argument |
| \e8 | 「ESC」「8」 | digit-argument |
| \e9 | 「ESC」「9」 | digit-argument |
| \C-x\C-v | 「Ctrl」+「x」「Ctrl」+「v」 | display-shell-version |
| \C-xA | 「Ctrl」+「x」「A」 | do-lowercase-version |
| \C-xB | 「Ctrl」+「x」「B」 | do-lowercase-version |
| \C-xC | 「Ctrl」+「x」「C」 | do-lowercase-version |
| \C-xD | 「Ctrl」+「x」「D」 | do-lowercase-version |
| \C-xE | 「Ctrl」+「x」「E」 | do-lowercase-version |
| \C-xF | 「Ctrl」+「x」「F」 | do-lowercase-version |
| \C-xG | 「Ctrl」+「x」「G」 | do-lowercase-version |
| \C-xH | 「Ctrl」+「x」「H」 | do-lowercase-version |
| \C-xI | 「Ctrl」+「x」「I」 | do-lowercase-version |
| \C-xJ | 「Ctrl」+「x」「J」 | do-lowercase-version |
| \C-xK | 「Ctrl」+「x」「K」 | do-lowercase-version |
| \C-xL | 「Ctrl」+「x」「L」 | do-lowercase-version |
| \C-xM | 「Ctrl」+「x」「M」 | do-lowercase-version |
| \C-xN | 「Ctrl」+「x」「N」 | do-lowercase-version |
| \C-xO | 「Ctrl」+「x」「O」 | do-lowercase-version |
| \C-xP | 「Ctrl」+「x」「P」 | do-lowercase-version |
| \C-xQ | 「Ctrl」+「x」「Q」 | do-lowercase-version |
| \C-xR | 「Ctrl」+「x」「R」 | do-lowercase-version |
| \C-xS | 「Ctrl」+「x」「S」 | do-lowercase-version |
| \C-xT | 「Ctrl」+「x」「T」 | do-lowercase-version |
| \C-xU | 「Ctrl」+「x」「U」 | do-lowercase-version |
| \C-xV | 「Ctrl」+「x」「V」 | do-lowercase-version |
| \C-xW | 「Ctrl」+「x」「W」 | do-lowercase-version |
| \C-xX | 「Ctrl」+「x」「X」 | do-lowercase-version |
| \C-xY | 「Ctrl」+「x」「Y」 | do-lowercase-version |
| \C-xZ | 「Ctrl」+「x」「Z」 | do-lowercase-version |
| \eA | 「ESC」「A」 | do-lowercase-version |
| \eB | 「ESC」「B」 | do-lowercase-version |
| \eC | 「ESC」「C」 | do-lowercase-version |
| \eD | 「ESC」「D」 | do-lowercase-version |
| \eE | 「ESC」「E」 | do-lowercase-version |
| \eF | 「ESC」「F」 | do-lowercase-version |
| \eG | 「ESC」「G」 | do-lowercase-version |
| \eH | 「ESC」「H」 | do-lowercase-version |
| \eI | 「ESC」「I」 | do-lowercase-version |
| \eJ | 「ESC」「J」 | do-lowercase-version |
| \eK | 「ESC」「K」 | do-lowercase-version |
| \eL | 「ESC」「L」 | do-lowercase-version |
| \eM | 「ESC」「M」 | do-lowercase-version |
| \eN | 「ESC」「N」 | do-lowercase-version |
| \eO | 「ESC」「O」 | do-lowercase-version |
| \eP | 「ESC」「P」 | do-lowercase-version |
| \eQ | 「ESC」「Q」 | do-lowercase-version |
| \eR | 「ESC」「R」 | do-lowercase-version |
| \eS | 「ESC」「S」 | do-lowercase-version |
| \eT | 「ESC」「T」 | do-lowercase-version |
| \eU | 「ESC」「U」 | do-lowercase-version |
| \eV | 「ESC」「V」 | do-lowercase-version |
| \eW | 「ESC」「W」 | do-lowercase-version |
| \eX | 「ESC」「X」 | do-lowercase-version |
| \eY | 「ESC」「Y」 | do-lowercase-version |
| \eZ | 「ESC」「Z」 | do-lowercase-version |
| \el | 「ESC」「l」 | downcase-word |
| \e\C-i | 「ESC」「Tab」 | dynamic-complete-history |
| \C-x\C-e | 「Ctrl」+「x」「Ctrl」+「e」 | edit-and-execute-command |
| \C-x) | 「Ctrl」+「x」「)」 | end-kbd-macro |
| \e> | 「ESC」「>」 | end-of-history |
| \C-e | 「Ctrl」+「e」 | end-of-line |
| \eOF | 「End」 | end-of-line |
| \e[4~ | 「End」 | end-of-line |
| \e[F | 「End」 | end-of-line |
| \C-x\C-x | 「Ctrl」+「x」「Ctrl」+「x」 | exchange-point-and-mark |
| \C-f | 「Ctrl」+「f」 | forward-char |
| \eOC | 「→」 | forward-char |
| \e[C | 「→」 | forward-char |
| \C-s | 「Ctrl」+「s」 | forward-search-history |
| \e[1;3C | 「Alt」+「→」 | forward-word |
| \e[1;5C | 「Ctrl」+「→」 | forward-word |
| \e[5C | 「Ctrl」+「→」 | forward-word |
| \e\e[C | 「ESC」「→」 | forward-word |
| \ef | 「ESC」「f」 | forward-word |
| \eg | 「ESC」「g」 | glob-complete-word |
| \C-x* | 「Ctrl」+「x」「*」 | glob-expand-word |
| \C-xg | 「Ctrl」+「x」「g」 | glob-list-expansions |
| \e^ | 「ESC」「^」 | history-expand-line |
| \e# | 「ESC」「#」 | insert-comment |
| \e* | 「ESC」「*」 | insert-completions |
| \e. | 「ESC」「.」 | insert-last-argument |
| \e_ | 「ESC」「_」 | insert-last-argument |
| \C-k | 「Ctrl」+「k」 | kill-line |
| \e[3;5~ | 「Ctrl」+「Delete」 | kill-word |
| \ed | 「ESC」「d」 | kill-word |
| \C-n | 「Ctrl」+「n」 | next-history |
| \eOB | 「↓」 | next-history |
| \e[B | 「↓」 | next-history |
| \en | 「ESC」「n」 | non-incremental-forward-search-history |
| \ep | 「ESC」「p」 | non-incremental-reverse-search-history |
| \C-o | 「Ctrl」+「o」 | operate-and-get-next |
| \C-x! | 「Ctrl」+「x」「!」 | possible-command-completions |
| \e= | 「ESC」「=」 | possible-completions |
| \e? | 「ESC」「?」 | possible-completions |
| \C-x/ | 「Ctrl」+「x」「/」 | possible-filename-completions |
| \C-x@ | 「Ctrl」+「x」「@」 | possible-hostname-completions |
| \C-x~ | 「Ctrl」+「x」「~」 | possible-username-completions |
| \C-x$ | 「Ctrl」+「x」「$」 | possible-variable-completions |
| \C-p | 「Ctrl」+「p」 | previous-history |
| \eOA | 「↑」 | previous-history |
| \e[A | 「↑」 | previous-history |
| \C-p | 「Ctrl」+「q」 | quoted-insert |
| \C-v | 「Ctrl」+「v」 | quoted-insert |
| \e[2~ | 「Insert」 | quoted-insert |
| \C-x\C-r | 「Ctrl」+「x」「Ctrl」+「r」 | re-read-init-file |
| \e[0n | クエリステータスレポート(応答) | redraw-current-line |
| \er | 「ESC」「r」 | redraw-current-line |
| \C-r | 「Ctrl」+「r」 | reverse-search-history |
| \e\C-r | 「ESC」「Ctrl」+「r」 | revert-line |
| \C-@ | 「Ctrl」+「@」 | set-mark |
| \e\C-e | 「ESC」「Ctrl」+「e」 | shell-expand-line |
| \C-x( | 「Ctrl」+「x」「(」 | start-kbd-macro |
| \e& | 「ESC」「&」 | tilde-expand |
| \et | 「ESC」「t」 | transpose-words |
| \C-_ | 「Ctrl」+「_」 | undo |
| \C-x\C-u | 「Ctrl」+「x」「Ctrl」+「u」 | undo |
| \C-u | 「Ctrl」+「u」 | unix-line-discard |
| \C-w | 「Ctrl」+「w」 | unix-word-rubout |
| \eu | 「ESC」「u」 | upcase-word |
| \C-z | 「Ctrl」+「z」 | vi-editing-mode |
| \C-y | 「Ctrl」+「y」 | yank |
| \e. | 「ESC」「.」 | yank-last-arg |
| \e_ | 「ESC」「_」 | yank-last-arg |
| \e\C-y | 「ESC」「Ctrl」+「y」 | yank-nth-arg |
| \ey | 「ESC」「y」 | yank-pop |

