cd 이외의 명령에 대한 Bash 자동 완성 변수

cd 이외의 명령에 대한 Bash 자동 완성 변수

환경 변수가 있습니다 $SCRIPT. 일반적으로 자동 완성을 사용할 수 있습니다

vim $SC<tab>

예상대로 작업이 완료됩니다. 일부 시스템에서는 작동하지 않습니다. bash 완료가 로드되었지만 이 경우 완료는 디렉터리( cd $SCRIPT_DIREC<tab>작동 중)에서만 작동합니다.

주로 bash 4.2에 문제가 있습니다.

무엇이 shopt그것을 가능하게 할 수 있나요?

편집: 내 설정을 작동하는 Bash 4.3 및 작동하지 않는 Bash 4.2(Ubuntu Server 12.04)와 비교했는데 shopt차이점이 거의 없었고(주로 4.3 특정) 나머지는 동일하게 설정했지만 아무것도 작동하지 않았습니다.

답변1

특히 문제는 쉘 내장 명령이 <tab>매개변수 이름을 확장할 수 있지만 외부 명령은 확장할 수 없다는 것입니다. 이것이 작동하는 이유는 다음과 같습니다 cd. echoread기타 내장 기능은 OP가 예상한 대로 계속 작동합니다.

가게와는 아무 상관이 없습니다.

/etc/bash_completionbash_completion 라이브러리( 내 12.04.4 시스템) 에 있습니다 . 버전 1.3에는 이러한 충돌 상황을 일으키는 요소가 있습니다. 1.99나 그 이전 어딘가에서 수정되었습니다.

bash_completion 라이브러리는 소스 코드가 있으면 자동으로 가져오므 ~/.bash_completion로 다음 내용이 포함된 파일을 생성하여 12.04.4 라이브러리에서 작동하지 않는 함수 정의를 오버로드하는 것이 좋습니다. 나는 몇 가지 작은 테스트를 수행했지만 내가 사용한 기계는 이것의 영향을 받지 않았으므로 주의해야 합니다.

# following functions are direct copy/pastes from
# bash_completion RELEASE: 1.99
# overloading `_longopt()' and adding `_variables()' and `_init_completion()'
# appears to be all that is needed to correct this.
# 
# http://unix.stackexchange.com/questions/126300/bash-autocomplete-variables-for-other-commands-than-cd

_init_completion()
{
    local exclude= flag outx errx inx OPTIND=1
    while getopts "n:e:o:i:s" flag "$@"; do
        case $flag in
            n) exclude+=$OPTARG ;;
            e) errx=$OPTARG ;;
            o) outx=$OPTARG ;;
            i) inx=$OPTARG ;;
            s) split=false ; exclude+== ;;
        esac
    done
    # For some reason completion functions are not invoked at all by
    # bash (at least as of 4.1.7) after the command line contains an
    # ampersand so we don't get a chance to deal with redirections
    # containing them, but if we did, hopefully the below would also
    # do the right thing with them...
    COMPREPLY=()
    local redir="@(?([0-9])<|?([0-9&])>?(>)|>&)"
    _get_comp_words_by_ref -n "$exclude<>&" cur prev words cword
    # Complete variable names.
    _variables && return 1
    # Complete on files if current is a redirect possibly followed by a
    # filename, e.g. ">foo", or previous is a "bare" redirect, e.g. ">".
    if [[ $cur == $redir* || $prev == $redir ]]; then
        local xspec
        case $cur in
            2'>'*) xspec=$errx ;;
            *'>'*) xspec=$outx ;;
            *'<'*) xspec=$inx ;;
            *)
                case $prev in
                    2'>'*) xspec=$errx ;;
                    *'>'*) xspec=$outx ;;
                    *'<'*) xspec=$inx ;;
                esac
                ;;
        esac
        cur="${cur##$redir}"
        _filedir $xspec
        return 1  
    fi
    # Remove all redirections so completions don't have to deal with them.
    local i skip  
    for (( i=1; i < ${#words[@]}; )); do
        if [[ ${words[i]} == $redir* ]]; then
            # If "bare" redirect, remove also the next word (skip=2).
            [[ ${words[i]} == $redir ]] && skip=2 || skip=1
            words=( "${words[@]:0:i}" "${words[@]:i+skip}" )
            [[ $i -le $cword ]] && cword=$(( cword - skip ))
        else
            i=$(( ++i ))
        fi
    done
    [[ $cword -eq 0 ]] && return 1
    prev=${words[cword-1]}
    [[ ${split-} ]] && _split_longopt && split=true
    return 0
}

_variables()
{
    if [[ $cur =~ ^(\$\{?)([A-Za-z0-9_]*)$ ]]; then
        [[ $cur == *{* ]] && local suffix=} || local suffix=
        COMPREPLY+=( $( compgen -P ${BASH_REMATCH[1]} -S "$suffix" -v -- \
            "${BASH_REMATCH[2]}" ) )
        return 0  
    fi
    return 1
}

_longopt()
{   
    local cur prev words cword split
    _init_completion -s || return
    case "${prev,,}" in
        --help|--usage|--version)
            return 0
            ;;
        --*dir*)
            _filedir -d
            return 0
            ;;
        --*file*|--*path*)
            _filedir
            return 0
            ;;
        --+([-a-z0-9_]))
            local argtype=$( $1 --help 2>&1 | sed -ne \
                "s|.*$prev\[\{0,1\}=[<[]\{0,1\}\([-A-Za-z0-9_]\{1,\}\).*|\1|p" )
            case ${argtype,,} in
                *dir*)
                    _filedir -d
                    return 0
                    ;;
                *file*|*path*)
                    _filedir
                    return 0
                    ;;
            esac
            ;;
    esac
    $split && return 0
    if [[ "$cur" == -* ]]; then
        COMPREPLY=( $( compgen -W "$( $1 --help 2>&1 | \
            sed -ne 's/.*\(--[-A-Za-z0-9]\{1,\}=\{0,1\}\).*/\1/p' | sort -u )" \
            -- "$cur" ) )
        [[ $COMPREPLY == *= ]] && compopt -o nospace
    elif [[ "$1" == @(mk|rm)dir ]]; then
        _filedir -d
    else
        _filedir
    fi
}

답변2

한 가지 방법은 별칭을 다음으로 설정하는 것입니다.

alias Script="<Your $Script Here>"

사용자의 .profile에서 /home/user/.profile다음 명령을 사용하여 가져옵니다.

$ . profile

그런 다음 자동으로 완료되는지 확인하십시오.

관련 정보