evitar que a conclusão do bash altere a variável de sublinhado $_

evitar que a conclusão do bash altere a variável de sublinhado $_

Ao usar o preenchimento de tabulação no bash, a $_variável é alterada:

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

(Ele <TAB><TAB>listará todos os arquivos no diretório atual, mas não acabo usando a saída e escrevo $_. O comando executado nesta linha será apenas cd $_.)

O comportamento esperado seria mudar para ./test.

Como posso evitar que a conclusão do bash seja alterada $_?

Responder1

Você está usando obash-completionpacote (ou um derivado). Para cada conclusão de argumento do cdcomando (conforme mostrado na complete -psaída):

complete -o nospace -F _cd cd

a _cdfunção é invocada para determinar as conclusões (ligeiramente editada por questões de brevidade):

_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
    ....

Por exemplo, quando você completa um diretório sem CDPATHconjunto, o último argumento visto para um comando visto é -de é colocado automaticamente em _. Existem vários outros caminhos de código nessa função com efeitos colaterais semelhantes.

Como _é um bash interno, um salvamento/restauração convencional (como paraIFS) não funcionará como esperado. Vocêpoderiafaça isso com um pouco de truque:

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

Você deve salvar _imediatamente ao entrar em uma função, :é o comando nulo, que não faz nada por si só, mas tem os efeitos colaterais usuais de um comando, como setting _. Esta operação de restauração será necessária para cada ponto de retorno de cada função potencialmente perturbadora. Há uma sutileza aqui também: normalmente _é definido imediatamente após o retorno de uma função (até o último argumento da chamada da função, como esperado), o que tornaria esse método ineficaz. Porém, isso não acontece quando uma função de conclusão é invocada, uma vez que não é invocada explícitamente. Não considero isso muito robusto...

(Eu prefiroexpansão da história, e atenha-se ao !$que não sofre esse problema.)

informação relacionada