bash 自动完成脚本

bash 自动完成脚本

我正在尝试为命令设置自动完成功能,该命令只需要一个参数,一个文件夹名称,

在 中/secure/kernel_builds/,我有以下三个子文件夹:

3.5.6/ 3.6.2/ source/

现在我想要自动完成,列出所有可能的子文件夹名称,但不列出名为 的子文件夹名称source,现在我正在使用一种非常愚蠢的方法来做到这一点,通过检查完成词是否以数字开头,

_avail_kernel_builds()
{
    case $COMP_CWORD in
        1)
            if [[ "${COMP_WORDS[COMP_CWORD]}" =~ ^[0-9] ]];then
                COMPREPLY=( /secure/kernel_builds/"${COMP_WORDS[COMP_CWORD]}"* )
            else
                COMPREPLY=( /secure/kernel_builds/"${COMP_WORDS[COMP_CWORD]}"[0-9]*/ )
            fi
            COMPREPLY=( "${COMPREPLY[@]#/secure/kernel_builds/}" )
            COMPREPLY=( "${COMPREPLY[@]%/}" )
            ;;
    esac    
}

有更好的方法吗?

答案1

内置函数为此目的compgen有一个参数:-X

-X 过滤模式
    filterpat 是用于文件名扩展的模式。它应用于列表
    由前面的选项和参数生成的可能的补全,以及每个
    完成匹配的filterpat将从列表中删除。领先!在过滤器中
    否定该模式;在这种情况下,任何不匹配 filterpat 的补全都会被删除。

所以你可能可以这样做:

_avail_kernel_builds() {
    case $COMP_CWORD in
        1) COMPREPLY=( $(cd /secure/kernel_builds; compgen -d -X "source") ) ;;
    esac
 }

所以compgen -d说“列出当前目录中的文件夹”,并-X "source"说“......但过滤掉任何名为“源”的内容。

答案2

您可以在循环中检查您(不)想要的字符串:

declare -a accept
declare -a reject
for s in "${COMPREPLY[@]}"; do
    if [[ "$s" =~ want ]]; then
        accept=( "${accept[@]}" "$s" )
    else
        reject=( "${reject[@]}" "$s" )
    fi
done

相关内容