UNIX/Linuxの部屋 complete(tcsh)コマンドの使い方

TOP UNIX/Linuxの部屋 UNIX/Linuxコマンド一覧 用語集 新版 由来/読み方辞書 環境変数マニュアル Cシェル変数 システム設定ファイル システムコール・ライブラリ ネットワークプログラミングの基礎知識 クラウドサービス徹底比較・徹底解説




コマンド complete(tcsh) コマンドの引数の補完の設定をする。tcsh の内部コマンド このエントリーをはてなブックマークに追加

最終更新


complete コマンドはシェル tcsh において、コマンドラインの引数の補完設定を行うための tcsh 内部コマンドである。コマンドごとにより便利なコマンドライン補完を行うことができる。


complete コマンドの基本的な使い方
tcsh は Ctrl-D と TAB で補完機能が使えるが、デフォルトではコマンドとファイル・ディレクトリのみが補完対象となっている。しかし、
  • telnet・rlogin … ホスト名
  • printenv … 環境変数
  • jlatex … *.tex
  • rmdir … ディレクトリ
というふうに、コマンドごとに補完対象を変えられるとさらに便利になる。complete コマンドを使うと、コマンドごとに補完対象をきめ細かく指定することができる。

以下に簡単な例をあげる。
% complete alias 'p/1/a/'
エイリアスのみを補完候補にする。ただし1番目の引数だけに対して効果がある。
% complete set 'p/1/s/'
シェル変数のみ。
% complete printenv 'p/*/e/'
環境変数のみ。何番目の引数でも効果あり。
% complete man 'p/*/c/'
コマンドのみ。何番目の引数でも効果あり。
% complete xdvi 'p/1/f:*.dvi/'
拡張子が .dvi であるファイルのみを補完候補にする。
% complete cc 'p/1/f:*.{c,cc}/'
拡張子が .c か .cc であるファイルのみを補完候補にする。

complete コマンドは、複雑で奥が深い。書式は
% complete コマンド名 '補完の種類/(マッチパターン or 引数番号)/補完対象/'
である。

complete コマンドの p について
まずは、'p/*/.../' という書き方を覚えよう。
`...' の部分に以下の文字を指定することで、補完候補を限定できる。
c コマンド
d ディレクトリ
f ファイル名
a エイリアス (alias コマンドで設定されているもの)
e 環境変数 (setenv コマンドで設定されているもの)
s シェル変数 (set コマンドで設定されているもの)
v 環境変数とシェル変数
u ユーザ名 (/etc/passwd に書かれているユーザ名)
g グループ名 (/etc/group に書かれているグループ名)
j ジョブ (jobs で表示されるジョブ)
l リミット (limit コマンド・ulimit コマンドで表示されるリミット名)
例をあげると、
% complete unalias 'p/*/a/'
補完対象はエイリアス
% complete unsetenv 'p/*/e/'
補完対象は環境変数
% complete foo 'p/*/es/'
補完対象は環境変数とシェル変数
また、その文字の後に : を付けると、シェルのワイルドカードが使える。
% complete foo 'p/*/f:*.txt/'
補完対象は *.txt にマッチするファイル
% complete foo 'p/*/u:a*/'
補完対象は a から始まるユーザ名

次に、'p/*/(... ... ...)/' という書き方。
例えば
% complete foo 'p/*/(abc def hij)/'
とすると、
% foo (TAB)
abc def hij
と、`()' で囲んだ文字列を補完候補にすることができる。

次に、'p/*/$xxx/' という書き方。
$xxx はシェル変数として扱われる。
% set xxx = (abc def hij)
% complete foo 'p/*/$xxx/'
と、
% complete foo 'p/*/(abc def hij)/'
は同じ意味である。ただし $xxx の内容を変更すると、補完対象も動的に変わる。よって、補完動作を行うときには必ず $xxx を設定しておかなくてはならない。

続いて、'p/*/`...`/' という書き方。
バッククォート `` で囲むことで、その中のコマンドを実行し、その結果を補完候補とする。例えば、talk コマンドの補完対象は現在ログイン中のユーザ名になってほしいので
% complete talk 'p/*/`users`/'
とする。これで、
% talk (Ctrl-D)
user1 user2
と、Ctrl-D や TAB を押すたびに users コマンドが実行され、ログイン中のユーザのみが補完対象となる。

complete コマンドの c について
次に、'c/XXX/YYY/' という書き方。
これは、「現在 XXX まで入力していたら、YYY を補完対象にする」という意味である。`YYY' の部分には、p/// の書き方のところで紹介した (... ... ...) ・ $xxx ・ `...` などの形式をそのまま使うことができる。
% complete foo 'c/abc/e/'
とすると、
% foo (Ctrl-D)
% foo a(Ctrl-D)
では、何も起こらない (デフォルト動作である、ファイル・ディレクトリの一覧を表示する)。しかし、abc とタイプした後に Ctrl-D を押すと
% foo abc(Ctrl-D)
CDPLAYER DISPLAY HOST LESS MPEGTABLES PWD USER
CVSEDITOR EDITOR HOSTDISPLAY LESSCHARSET OSTYPE SHELL VENDOR
と、環境変数の一覧を表示する。

% complete foo 'c/abc/(xx yy zz)/'
ならば、
% foo abc(Ctrl-D)
xx yy zz
となる。

特に、これはオプションを補完候補にする場合に有効である。例えば
% complete foo 'c/-/(x y z)/'
% foo -(Ctrl-D)
x y z
と、オプションの一覧を手軽に見ることができる (もちろん TAB で補完もできる)。さらに、`XXX' の部分には、メタキャラクタを使うことができる。
% complete foo 'c/-[abc]/(x y z)/'
% foo -a(Ctrl-D)
x y z
% foo -b(Ctrl-D)
x y z
この例では、-a か -b か -c が入力されると、x y z という補完候補を表示する。
% complete foo 'c/-A*/(x y z)/'
だと、-A から始まる文字列 ( -A や -Ab -Ac -Aabc など) が入力されているときは x y z が補完対象になるし、
% complete foo 'c/-*A/(x y z)/'
は、- から始まり A で終わる文字列 (-*A にマッチする文字列) が入力されているとき、x y z が補完対象になる。

complete コマンドの n について
最後に 'n/XXX/YYY/'。
これは 'c/XXX/YYY/' とほぼ同じであるが、違うのは `XXX' の次の引数に対して `YYY' を補完対象にすることである。
% complete foo 'c/XXX/(YYY)/'
だと、`XXX' の直後に TAB を押すと
% foo XXX(TAB)
YYY
となるが、
% complete foo 'n/XXX/(YYY)/'
% foo XXX(TAB)
と、`XXX' の直後に TAB を押しても何も起こらない。しかし
% foo XXX (TAB)
`XXX' の後に空白を入れて TAB を押すと `YYY' が補完対象となる。

再度、'p///' について補足説明。
実は p/// は、何番目の引数かによって、補完対象を限定する命令である。
% complete foo1 'p/1/c/'
補完対象はコマンド名。ただし1番目の引数のみ。
% complete foo2 'p/3/c/'
補完対象はコマンド名。ただし3番目の引数のみ。
% complete foo3 'p/*/c/'
補完対象はコマンド名。何番目の引数でも有効。
上記の例では、
% foo1 (Ctrl-D)
1番目の引数なので、コマンド名の一覧を表示
% foo1 foo (Ctrl-D)
2番目の引数に対しては設定されていないので、ファイル・ディレクトリの一覧を表示 (デフォルト動作)
% foo2 (Ctrl-D)
1番目の引数に対しては設定されていないので、ファイル・ディレクトリの一覧を表示 (デフォルト動作)
% foo2 foo bar (Ctrl-D)
3番目の引数なので、コマンド名の一覧を表示
となる。foo3 は何番目の引数であっても、常にコマンド名を表示する。

complete コマンドの p c n の使い分けについて
最後に、p/// c/// n/// の使い分けについて。
例えば find コマンドは、-type の後に f s b c l などの引数を書く。そういう場合、
% complete find 'n/-type/(f s b c l)/'
とする。一方、find の引数には -type の他にも、-name -size -inum -exec など多くの引数を取ることができる。この場合には
% complete find 'c/-/(type name size inum exec)/'
と、n/// でなく c/// を使うわけだ。一方 p/// は何番目の引数かを指定したいとき、例えば
% complete telnet 'p/1/(localhost host1 host2)/' 'p/2/(http ftp pop3)/'
などいうふうに使う。また、特に何番目の引数かを指定しない場合でも
% complete foo 'p/*/a/'
としてもよい。


さて、一通り説明をしたので実際に設定例をあげよう。まずは先程あげた簡単な例。
% complete alias 'p/1/a/'
% complete printenv 'p/*/e/'
% complete man 'p/*/c/'
% complete xdvi 'p/1/f:*.dvi/'
% complete cc 'p/1/f:*.{c,cc}/'
これらはもう説明はいらないだろう。

complete コマンドの例 - find 編
次に find コマンド。
find コマンドは -type -name -size などのオプションがあり、
'c/-/(type name size inum exec print)/'
-type の後には f s b c l などの引数を取る。
'n/-type/(f s b c l)/'
-user の後にはユーザ名、-group の後にはグループ名を取る。
'n/-user/u/' 'n/-group/g/'
また、find はディレクトリ名を受け取り、そこを起点にファイルシステムを検索するので、
'p/*/d/'
も指定しよう。これらの設定を反映させるには、全て繋げればよい。つまり
% complete find 'c/-/(type name size inum exec print)/' 'n/-type/(f s b c l)/' 'n/-user/u/' 'n/-group/g/' 'p/*/d/'
とすればよい。ここで大事なのは、'p/*/d/' を最後に持っていくことである。この設定では
% find -(Ctrl-D)
type name size inum exec print
となるが、もし 'p/*/d/' を先頭に持っていき
% complete find 'p/*/d/' 'c/-/(type name size inum exec print)/' ...
% find -(Ctrl-D)
とすると、tcsh は - がディレクトリの一部であると判断し、- から始まるディレクトリの一覧を表示する。もし - から始まるディレクトリが存在しなければ、何も表示しなくなる。狭い範囲の設定を先に (左に) 書き、広い範囲の設定は後に (右に) 書く、ということを覚えておこう。

complete コマンドの例 - talk 編
次に talk コマンド。
talk の引数はユーザ名であるが、現在ログイン中のユーザ名だけを補完対象にしたい。
% finger | awk '{print $1}' | tail +2 | sort -u
で、現在ログインしているユーザ名だけをピックアップできるので、これを complete コマンドの中に組み込めばよい。

まずは先程の例から '' を外し、代わりに \ でエスケープする。
finger | awk \{print\ \$1\} | tail +2 | sort -u
これは、tcsh (sh・csh も同じ) では、'' の中に ' を含めることができないからである。perl と違って、'\'' としても、真ん中の ' はエスケープされない。'' の中では \ は \ そのものとして扱われるので、メタキャラクタをエスケープする能力を失ってしまうのである。今回は、最終的に
complete finger 'p/.../.../'
と、全体を '' で囲みたいので awk の部分で '' を使わないようにするのである。次に全体を `` (バッククォート) で囲む。
`finger | awk \{print\ \$1\} | tail +2 | sort -u`
さらに p/1// の中に入れる (1番目の引数が対象)。
p/1/`finger | awk \{print\ \$1\} | tail +2 | sort -u`/
全体を '' で囲む。
'p/1/`finger | awk \{print\ \$1\} | tail +2 | sort -u`/'
先頭に complete とコマンド名を付けて できあがり。
% complete talk 'p/1/`finger | awk \{print\ \$1\} | tail +2 | sort -u`/'

complete コマンドの例 - telnet 編
最後に telnet コマンド。
telnet コマンドは、
% telnet ホスト名
% telnet ホスト名 ポート番号 (あるいはポート名)
という引数を受ける。そこで、ホスト名とポート名を補完するようにしよう。ホスト名は
% set hosts=(foo.bar.com hoge.fuga.ac.jp)
と、シェル変数 $hosts で設定しておく。

また、ポート名は /etc/services から取得する。/etc/services の中身は
ポート名 ポート番号/プロトコル
という形式になっており、# はコメントを表すので、
% cat /etc/services | awk '{print $1}' | sed 's/#.*//' | sort -u
でプロトコルの一覧を得られる。ただしこれでは問題がある。FreeBSD の /etc/services には
sql*net 66/tcp #Oracle SQL*NET
という行が含まれているのだが、このように * や ? が含まれていると、補完動作をしたとき (Ctrl-D や TAB を押したとき) に、tcsh が * や ? をワイルドカードとみなして、パターンマッチを行おうとする。そこで
% cat /etc/services | awk '{print $1}' | sed 's/#.*//' | sort -u | sed 's/\*/\\*/g'
と、`*' を `\*' に置換しなければならない。

あとはこれをひとつにまとめればよいのだが、先に述べたように、まず '' を含まない形に変更すると
% cat /etc/services | awk \{print\ \$1\} | sed s/#.\*// | sort -u | sed s/\\\*/\\\\\*/g
となる。あとは、1番目の引数ならホスト名を、2番目の引数ならポート名を補完させればよい。ただし、sed の引数に `/' を渡しているので、`p///' という形式は使えない。代わりに`p@@@' や `p^^^' という書き方ができる。最終的には
% set hosts=(foo.bar.com hoge.fuga.ac.jp)
% complete telnet 'p/1/$hosts/' 'p@2@`cat /etc/services | awk \{print\ \$1\} | sed s/#.\*// | sort -u | sed s/\\\*/\\\\\*/g`@'
となる。長いね…。

コマンド補完設定
これまで引数の補完について述べてきたが、ここでコマンド補完の設定にも触れておこう。tc と入力して補完しようとすると、
% tc (Ctrl-D)
tcsh tconv tclsh tcpdump tcpslice
などと、tc から始まるコマンドの一覧が表示される。もしこの中で tcpdump だけを補完対象としたければ、
% complete -tc* 'p/0/(tcpdump)/'
とする。p/0// の 0 は 0 番目の引数、つまりコマンド自身を表している。すると、
% tc (Ctrl-D)
tcpdump
となり、tcpdump 以外のコマンドが補完候補から外される。

なお、シェル変数 fignore で指定したファイル群は補完対象から外される。