
在 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
您必須_
在進入函數時立即儲存,:
這是空命令,它本身不執行任何操作,但具有命令的常見副作用,例如設定_
。每個潛在破壞性功能的每個返回點都需要此復原操作。這裡也有一個微妙之處:通常_
在函數返回後立即設定(如預期的那樣,到函數呼叫的最後一個參數),這將使方法無效。但是,當呼叫完成函數時不會發生這種情況,因為它不是明確調用的。我不認為這非常強大......
(我比較喜歡歷史擴展,並堅持!$
哪個不會遇到這個問題。