Um traçado simples
Primeiro, você pode descobrir o que realmente acontece quando você usa o bash completion com o comando cd :
$ complete -p | grep cd
complete -F _filedir_xspec cdiff
complete -o nospace -F _cdrecord wodim
complete -o nospace -F _cdrecord cdrecord
complete -o nospace -F _cd cd
Você pode ver uma função _cd será chamada quando você usar a conclusão com cd . Então você sabe que alguma coisa aconteceu dentro da função _cd , o valor da variável $_ foi alterado.
Olhando para a função _cd : (No meu Ubuntu 12.04.4, está em /etc/bash_completion )
# This meta-cd function observes the CDPATH variable, so that cd additionally
# completes on directories under those specified in CDPATH.
#
_cd()
{
local cur IFS=$'\n' i j k
_get_comp_words_by_ref cur
# try to allow variable completion
if [[ "$cur" == ?(\)\$* ]]; then
COMPREPLY=( $( compgen -v -P '$' -- "${cur#?(\)$}" ) )
return 0
fi
....
_filedir -d
if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
i=${COMPREPLY[0]}
if [[ "$i" == "$cur" && $i != "*/" ]]; then
COMPREPLY[0]="${i}/"
fi
fi
return 0
}
Ele faz muitas coisas, faz com que seu antigo $_ seja perdido. Talvez você tenha problemas com a linha _filedir -d . (No meu teste, eu tenho $_ alterado para -d )
Para evitar que o seu $_ desejado seja perdido, você pode salvar seu valor imediatamente quando inserir a função _cd e restaurar esse valor para $_ antes de deixar o _cd :
_cd()
{
local __=$_
....
: $__
return 0
}
O truque aqui é : , isso significa não fazer nada em bash e tem um parâmetro $__ (que é seu valor $_ desejado), fazendo com que $_ seja definido como valor antigo antes de você insira a função _cd .
Conclusão
É muito difícil fazer com que bash completion não desperdice a variável $_ . Com o exemplo acima, você só impediu que ele fosse descartado com cd . Com outras funções em bash_completion e todos os arquivos em /etc/bash_completion.d/ , você precisa fazer a mesma coisa. Esta não é uma solução robusta.
Se você deseja obter o último parâmetro da última linha de comando, tente usar bash history expansion :
$ echo 1 2 3
1 2 3
$ echo !$
echo 3
3