Existe uma solução alternativa para a remoção de arquivos do Debian $ _?

4

Eu tenho anos de experiência no Linux do Slackware e nunca vi esse problema lá. Ultimamente eu tenho administrado servidores Debian, e isso se tornou um aborrecimento.

Eu freqüentemente uso "$ _" em um comando bash para repetir o argumento final do comando previamente digitado. Às vezes, obtenho o seguinte comportamento:

dschrag@mo:~/dev/dancer$ ls -l app/db/schema/
total 12
-rw-r--r-- 1 dschrag dschrag 268 May 19 10:51 gau_account.sql
-rw-r--r-- 1 dschrag dschrag 558 May 19 13:02 gau_import.sql
-rw-r--r-- 1 dschrag dschrag 270 May 19 13:09 gau_source.sql
dschrag@mo:~/dev/dancer$ cd $_
-bash: cd: _filedir: No such file or directory
dschrag@mo:~/dev/dancer$

Eu olhei em volta o suficiente para ver que _filedir é usado em muitas funções de shell predefinidas (por padrão) definidas em /usr/share/bash-completion/bash_completion .

Eu uso o preenchimento de arquivos sem pensar, ao ponto que é difícil para mim descobrir exatamente o que estou fazendo quando essa falha ocorre. Alguém se deu ao trabalho de cavar mais fundo nisso?

    
por dmaestro12 19.05.2014 / 20:01

2 respostas

2

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
    
por 19.05.2014 / 21:08
3

Você tem a conclusão programável ("conclusão do bash") ativada. Isso é feito com o sourcing de /etc/bash_completion ou /usr/share/bash-completion/bash_completion em algum lugar no seu bashrc. Por exemplo, no esqueleto bashrc em jessie:

# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
  if [ -f /usr/share/bash-completion/bash_completion ]; then
    . /usr/share/bash-completion/bash_completion
  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi

Uma das conclusões está sobrescrevendo $_ . A solução rápida seria não carregar a conclusão do bash.

Outra solução alternativa é concluir o nome do arquivo com a função complete-filename em vez da função complete . Isso significa pressionar ESC , / ou Alt + / (dependendo da configuração do terminal) em vez de < kbd> Separador . Você pode alterar quais chaves estão vinculadas a bind ou editando ~/.inputrc .

E, suponho, envie um relatório de bug para a conclusão do bash.

    
por 19.05.2014 / 20:33