例えば、manの引数にコマンド名を補完しようとしても[Tab]では補完されない(コマンド名補完は[Alt-!]で可能だが)といった経験があると思う。bash-completionはそのコマンドの文法(オプション)に合わせて補完してくれるので[Tab]を叩いていればよい。
ただし、manの場合は存在するコマンドから補完するのでなく、manが存在するコマンド名を補完しようとするみたいなので、初回はその検索に時間を多少要する。
それが、rpm や yum のパッケージ名になるとDBが大きいので顕著になるので注意。キャッシュに残っていれば速いがそうでない場合は、"rpm -qa"とかをしているのと同じスピードになってしまうので。
次にtarコマンドの場合、foo.tbz2 と hoge.tgz の2つのみがカレントにあるとき
$ tar zxf [Tab]
また、hello.sとhello.oの2つみがある場合も
$ vi [Tab]
svnやgit、mercurialなどのサブコマンドが必要な場合でもそれぞれに合った補完をしてくれる。
また、killのようにPIDが必要な場合でも存在するPIDが補完される(PIDは順に振られるため補完対象が決定するまでタイプしてると結局全部タイプしてたとかということもあるので、あまり役に立たないけど)。
極めつけは、make。Makefile内のターゲットを都度確認して補完してくれるのだ。
「clean」ターゲットがあれば"make c[Tab]"で補完してくれるが、無い場合は補完しないといった具合に。更にMakefileからincludeされているファイルも解析するので、「menuconfig」や「uImage」なども補完してくれる(その分補完に時間が掛かるが)。
もちろん、その他コマンドに対してもキメ細かな補完をしてくれる。
インストールは以下で完了。
$ sudo yum -y install bash-completion
ただし、デフォルトの状態ではお節介過ぎる補完があるので修正をする。
"~/De[Tab]"とすると、通常は"~/Desktop/"と補完されるが、bash-completionの場合"/home/okap/Desktop/"とお節介なほどに補完されてしまう。「~」の方がスッキリしていて見やすいのでそこをホームディレクトリ名に展開されると長ったらしくなり困るのだ。
$ sudo vim /etc/bash_completion
...
# This function expands tildes in pathnames
#
_expand()
{
[ "$cur" != "${cur%\\}" ] && cur="$cur\\"
# expand ~username type directory specifications
if [[ "$cur" == \~*/* ]]; then
eval cur=$cur
elif [[ "$cur" == \~* ]]; then
cur=${cur#\~}
COMPREPLY=( $( compgen -P '~' -u $cur ) )
return ${#COMPREPLY[@]}
fi
}
...
eval cur=$cur
↓
#eval cur=$cur
:
これで新しいセッションでは、「~」がホームディレクトリ名に展開されなくなる。
はじめまして.
返信削除>「~」の方がスッキリしていて見やすいのでそこをホームディレクトリ名に展開されると長ったらしくなり困るのだ。
ごもっとも!と思い,さっそく設定させていただきました^^
しかし,scpなどでリモート名:ファイル名といった形($ scp hoge.com:~/Desktop/)をとると思うのですが,ここの~はこのままだとまだ展開されてしまうみたいです.
もしかして解決法をご存じではないでしょうか?
よろしくお願い致します.
確かにそうですね。
返信削除しかし、scpの場合top_dirはリモートのユーザのhome_dirになっているので、パス指定には「~」は不要です。($ scp hoge.com:Desktop/ で OK)
この指定でもちゃんとリモートファイル名も補完され、かつウザったい /home/user/ は付加されませんでした。
ちなみに、各コマンドの固有部分は /etc/bash_completion.d/以下にあります。
scpの場合は、/etc/bash_completion.d/ssh が指している実態ファイル内で「~」展開をしているようです。
なるほど~
返信削除大変参考になりました.ありがとうございます.