bash脚本中的自动完成功能

时间:2016-09-21 18:32:23

标签: bash autocomplete

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

repo() {
 cd ~/Desktop/_REPOS/$1
}

我试着阅读this SO post的想法,但很快就迷失了,因为我仍然很吵。但

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

>ls ~/Desktop/_REPOS/
folder1
hellofolder
stackstuff

>repo sta[TAB] fills in as: repo stackstuff

2 个答案:

答案 0 :(得分:8)

实际上你可以从geirha's answer借用相当多的代码:

# 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

for循环遍历目录中的所有文件,这些文件以作为_repo_complete函数的第二个参数给出的字符串开头(这是要自动完成的字符串)。

将代码添加到.bashrc,它应该可以使用!

答案 1 :(得分:8)

如果我理解正确的话,我会看到两个选项来获取您想要的内容,即自定义cd命令的路径自动完成。

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

    CDPATH="$CDPATH":"$HOME"/Desktop/_REPOS
    

    现在,在任何目录中,您都可以键入cd Space Tab ,除了当前目录的子目录外,还可以输入{的所有目录{1}}会出现。 (这也是这种方法的缺点:更加混乱。)

  2. 您可以为~/Desktop/_REPOS添加完成功能。您已经开始的方式,您需要.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
    

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

    $ compgen -d "$HOME"/Desktop/_REPOS/f
    /home/me/Desktop/_REPOS/folder1
    /home/me/Desktop/_REPOS/folder2
    
    参数展开中的

    $ arr=(/path/to/dir1 /path/to/dir2) $ echo "${arr[@]##*/}" dir1 dir2 会从##*/的每个元素中移除*/的最长匹配,即,只留下最后一个正斜杠之后的内容 - 恰好是什么我们想要。

    现在我们把它放在一起,放到一个函数中:

    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[@]##*/}") } ,以及使用.bashrc自动完成的说明:

    repo

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

    $1
  3. 您点击标签的次数取决于readline settings,例如repo () { cd ~/Desktop/_REPOS/"$1" }

    <强>参考