bash 補完がアンダースコア変数 $_ を変更するのを防ぐ

bash 補完がアンダースコア変数 $_ を変更するのを防ぐ

bash でタブ補完を使用する場合、$_変数は変更されます。

$ mkdir test
$ cd <TAB><TAB> $_
bash: cd: -d: invalid option
cd: usage: cd [-L|[-P [-e]]] [dir]

(は<TAB><TAB>現在のディレクトリ内のすべてのファイルを一覧表示しますが、出力は使用せず、$_代わりに書き込みます。この行で実行されるコマンドは になりますcd $_。)

期待される動作は に変更することです./test

bash 補完が変更されないようにするにはどうすればよいですか$_?

答え1

使用しているのはbash-completionパッケージ(または派生パッケージ)。cdコマンドの各引数補完(出力に表示されるcomplete -p)ごとに、次のようになります。

complete -o nospace -F _cd cd

関数_cdは補完を決定するために呼び出されます (簡潔にするために少し編集されています)。

_cd()
{
    local cur prev words cword
    _init_completion || return

    local IFS=$'\n' i j k

    compopt -o filenames

    if [[ -z "${CDPATH:-}" || "$cur" == ?(.)?(.)/* ]]; then
        _filedir -d
        return 0
    fi
    ....

たとえば、CDPATH設定されていないディレクトリで を完了すると、表示されたコマンドの最後に表示された引数は となり-d、これが自動的に に配置されます_。この関数には、同様の副作用を持つ他のコード パスがいくつかあります。

_bashの内部なので、従来の保存/復元(IFS)は期待通りには機能しません。できたちょっとしたトリックを使ってやってみます:

_cd()
{
    local save_="$_"
    ...
    : $save_
    return 0

_関数に入るとすぐに保存する必要があります:。はヌル コマンドで、それ自体は何も行いませんが、 の設定などのコマンドの通常の副作用があります_。この復元操作は、潜在的に混乱を招く可能性のある各関数の各戻りポイントで必要になります。ここでも微妙な点があります。通常、 は_関数から戻った直後に設定されます (予想どおり、関数呼び出しの最後の引数に設定されます)。そのため、この方法は無効になります。ただし、補完関数が呼び出された場合は、明示的に呼び出されないため、この処理は行われません。これはあまり堅牢ではないと思います...

(私は歴史の拡大、そして!$この問題の影響を受けないものに固執してください。

関連情報