bash脚本中的自动完成功能

Ril*_*n42 1 bash autocomplete

我试图在bash脚本中自动填充文件夹名称.如果我输入完整的文件夹名称一切正常,但我不知道如何自动完成名称.有任何想法吗?

repo() {
 cd ~/Desktop/_REPOS/$1
}
Run Code Online (Sandbox Code Playgroud)

我试着阅读这篇SO帖子的想法,但很快就迷路了,因为我还是很吵.

GOAL(上面的repo函数包含在我的bashrc中):

>ls ~/Desktop/_REPOS/
folder1
hellofolder
stackstuff

>repo sta[TAB] fills in as: repo stackstuff
Run Code Online (Sandbox Code Playgroud)

Eur*_*uro 8

实际上你可以从geirha的答案中借用相当多的代码:

# this is a custom function that provides matches for the bash autocompletion
_repo_complete() {
    local file
    # iterate all files in a directory that start with our search string
    for file in ~/Desktop/_REPOS/"$2"*; do
        # If the glob doesn't match, we'll get the glob itself, so make sure
        # we have an existing file. This check also skips entries
        # that are not a directory
        [[ -d $file ]] || continue

        # add the file without the ~/Desktop/_REPOS/ prefix to the list of 
        # autocomplete suggestions
        COMPREPLY+=( $(basename "$file") )
    done
}

# this line registers our custom autocompletion function to be invoked 
# when completing arguments to the repo command
complete -F _repo_complete repo
Run Code Online (Sandbox Code Playgroud)

for循环遍历目录中,在给定的第二个参数字符串开头的所有文件_repo_complete的功能(这是要自动完成的字符串).

添加代码到你的.bashrc,它应该工作!


Ben*_* W. 8

cd如果我理解正确的话,我会看到两个选项来获得你想要的东西,即自定义命令的路径自动完成.

  1. 您可以将父目录添加~/Desktop/_REPOSCDPATH环境变量中:

    CDPATH="$CDPATH":"$HOME"/Desktop/_REPOS
    
    Run Code Online (Sandbox Code Playgroud)

    现在,您可以从任何目录中键入cd SpaceTab,除了当前目录的子目录外,~/Desktop/_REPOS还将显示所有目录.(这也是这种方法的缺点:更加混乱.)

  2. 您可以添加完成功能.bashrc.你开始的方式,你想要所有目录的基本名称~/Desktop/_REPOS.要获得目录的自动完成,我们可以使用compgen -d内置:

    $ compgen -d "$HOME"/Desktop/_REPOS/
    /home/me/Desktop/_REPOS/folder1
    /home/me/Desktop/_REPOS/folder2
    /home/me/Desktop/_REPOS/stackstuff
    /home/me/Desktop/_REPOS/hellofolder
    
    Run Code Online (Sandbox Code Playgroud)

    这将返回所有子目录的名称.当路径更具体时,它减少到更少的候选者:

    $ compgen -d "$HOME"/Desktop/_REPOS/f
    /home/me/Desktop/_REPOS/folder1
    /home/me/Desktop/_REPOS/folder2
    
    Run Code Online (Sandbox Code Playgroud)

    要删除除基本名称之外的所有内容,我们使用shell参数扩展,如下所示:

    $ arr=(/path/to/dir1 /path/to/dir2)
    $ echo "${arr[@]##*/}"
    dir1 dir2
    
    Run Code Online (Sandbox Code Playgroud)

    ##*/在参数扩展中删除了*/每个元素的最长匹配arr,即,只留下最后一个正斜杠之后的内容 - 正是我们想要的.

    现在我们将它们组合在一起并形成一个函数:

    _comp_repo () {
        # Get list of directories
        # $2 is the word being completed
        COMPREPLY=($(compgen -d "$HOME"/Desktop/_REPOS/"$2"))
    
        # Reduce to basenames
        COMPREPLY=("${COMPREPLY[@]##*/}")
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这与您.bashrc使用它的指令一起进入自动完成repo:

    complete -F _comp_repo repo
    
    Run Code Online (Sandbox Code Playgroud)

    请注意,您的repo函数应引用$1参数以确保它正确处理具有特殊字符(空格,制表符...)的目录名称:

    repo () {
        cd ~/Desktop/_REPOS/"$1"
    }
    
    Run Code Online (Sandbox Code Playgroud)

您击中的次数Tab取决于读取线设置,例如show-all-if-ambiguous.


参考