데비안 파일 완성 쓰레기$_를 수정할 수 있는 방법이 있나요?

데비안 파일 완성 쓰레기$_를 수정할 수 있는 방법이 있나요?

나는 Slackware Linux에 대해 다년간의 경험을 갖고 있지만 이 문제를 본 적이 없습니다. 나는 최근 데비안 서버를 관리하고 있는데 이것이 짜증나는 일이 되었습니다.

나는 종종 이전에 입력한 명령의 마지막 인수를 반복하기 위해 bash 명령에서 "$_"를 사용합니다. 때때로 다음과 같은 동작이 나타납니다.

dschrag@mo:~/dev/dancer$ ls -l 앱/db/schema/
총 12개
-rw-r--r-- 1 dschrag dschrag 268 5월 19일 10:51 gau_account.sql
-rw-r--r-- 1 dschrag dschrag 558 5월 19일, 13:02 gau_import.sql
-rw-r--r-- 1 dschrag dschrag 270 5월 19일 13:09 gau_source.sql
dschrag@mo:~/dev/dancer$ cd $_
-bash: cd: _filedir: 해당 파일이나 디렉터리가 없습니다.
dschrag@mo:~/dev/dancer$

주위를 둘러보니 _filedir에서 사용된 것이었습니다 /usr/share/bash-completion/bash_completion.

나는 파일 완성 기능을 아무 생각 없이 사용하기 때문에 이 결함이 발생했을 때 내가 무엇을 하고 있었는지 파악하기가 어렵습니다. 이 문제를 조사하는 데 어려움을 겪은 사람이 있습니까?

답변1

프로그래밍 가능한 완료("bash 완료")를 활성화했습니다. 이는 소스 /etc/bash_completion나 bashrc의 어딘가를 통해 /usr/share/bash-completion/bash_completion수행 됩니다. 예를 들어, jessie의 bashrc 스켈레톤에서는 다음과 같습니다.

# 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

완료되는 작업 중 하나는 멀칭입니다 $_. 빠른 수정은 bash 완성을 로드하지 않는 것입니다.

complete-filename또 다른 해결 방법은 이 함수 대신 이 함수를 사용하여 파일 이름 완성을 완료하는 것입니다 complete. 이는 대신 ESC, /또는 Alt+ /(단말기 설정에 따라) 를 누르는 것을 의미합니다 Tab. bind를 사용하거나 편집하여 이러한 키가 바인딩된 키를 변경할 수 있습니다 ~/.inputrc.

또한 bash 완성에 대한 버그 보고서를 제출하고 싶습니다.

답변2

단순 추적

cd먼저, bash 명령 완성을 사용할 때 실제로 무슨 일이 일어나는지 알아낼 수 있습니다 .

$ 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

_cd완성을 사용하면 함수가 호출되는 것을 볼 수 있습니다 cd. 따라서 _cd함수 내부에서 $_변수 값이 변경된 문제가 발생했다는 것을 알 수 있습니다 .

기능을 확인하세요 _cd: (내 Ubuntu 12.04.4에서는 /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
}

$_그것은 당신이 옛 자아를 잃게 만드는 많은 일을 할 것입니다 . 아마도 배선에 문제가 있는 것 같습니다 _filedir -d. (내 테스트에서는 $_로 변경되었습니다 -d.)

원하는 내용을 잃지 않으려면 함수에 들어가자마자 해당 값을 저장한 다음 $_종료하기 전에 _cd복원 할 수 있습니다.$__cd

_cd()
{
    local __=$_

    ....

    : $__
    return 0
}

여기서 중요한 점은 :에서 아무 작업도 하지 않고 매개변수 (원하는 값 ) bash가 있어서 함수를 입력하기 전에 이전 값으로 설정된다는 것입니다.$__$_$__cd

결론적으로

bash completion변수를 낭비하지 않는 것은 매우 어렵습니다 $_. 위의 예에서는 를 사용합니다 . cd의 다른 기능 bash_completion과 아래의 모든 파일에 대해서도 /etc/bash_completion.d/동일한 작업을 수행해야 합니다 . 이는 신뢰할 수 있는 솔루션이 아닙니다.

마지막 명령줄의 마지막 인수를 얻으려면 다음을 사용해 보십시오 bash history expansion.

$ echo 1 2 3
1 2 3
$ echo !$
echo 3
3

관련 정보