我不喜欢这里的任何答案,并想提供几个具体的例子。
有时我有许多具有共同前缀的目录,并且希望能够通过键入目录名称的唯一部分(位于目录名称的中间或结尾)来完成它们。
我能够编写一个完成函数来完成这个:
_cd(){
# Backup old nullglob setting
local shoptbakup="`shopt -p nullglob`"
shopt -s nullglob
local cur opts i opt
local IFS=$'\n'
cur="${COMP_WORDS[COMP_CWORD]}"
# Home directory substitution
if [[ "${cur:0:1}" == '~' ]]; then
cur="$HOME/${cur:1}"
fi
if [[ $cur == */* ]]; then
opts=(${cur}*/)
else
opts=(*${cur}*/)
fi
# Prevent trailing//
i=0
for opt in "${opts[@]}"; do
#opts[$i]=${opt%${opt##*[!/]}}
opts[$i]=${opt%/}
i=$((i+1))
done
# Restore nullglob setting
eval "$shoptbakup" 2>/dev/null
COMPREPLY=("${opts[@]}")
}
complete -o filenames -o bashdefault -o nospace -F _cd cd
所以现在根据我的提示,我可以这样做:
$ ls
test 6/ test 7/ test 8/ test1/ test2/ test3/ test4/ test5/
$ cd 7[TAB]
它会自动完成到:
$ cd test\ 7/
您可能想要使用可编程完成的另一个原因是,如果您编写脚本并希望能够为您列出或完成选项。这个页面有一些非常好的例子:
http://fahdshariff.blogspot.com/2011/04/writing-your-own-bash-completion.html
这是一个例子:
假设我有一个名为 listanimals 的脚本。我可以写一个补全函数来帮助填写选项
# complete sendevent
_listanimals()
{
local cur=${COMP_WORDS[COMP_CWORD]}
local prev=${COMP_WORDS[COMP_CWORD-1]}
if [[ $prev == "--sort-direction" ]]; then
COMPREPLY=( $( compgen -W "horizontal vertical" -- $cur ) )
return 0
elif [[ $prev == "--type" ]];then
COMPREPLY=( $( compgen -W "mammals reptiles birds fish marsupials insects misc" -- $cur ) )
return 0
elif [[ $prev == "--size" ]]; then
COMPREPLY=( $( compgen -W "tiny small medium large huge" -- $cur ) )
return 0
fi
# completing an option
if [[ "$cur" == --* ]] || [[ $cur == "" ]]; then
COMPREPLY=( $( compgen -W "--sort-direction --type --size" -- $cur ) )
fi
}
complete -F _listanimals listanimals
现在我可以这样做了:
$ listanimals --[TAB][TAB]
--size --sort-direction --type
$ listanimals --t[TAB]
这会自动填写:
$ listanimals --type
那么我可以这样做:
$ listanimals --type [TAB][TAB]
birds fish insects mammals marsupials misc reptiles
而且我相信你可以弄清楚其余的。这是一个工作示例,因此如果您想尝试一下,只需将其复制/粘贴到文件中(例如 sample.sh)并在 bash source sample.sh 中获取它。您实际上并不需要一个名为 listanimals 的脚本。
希望有人会觉得这很有用,因为我发现很难弄清楚。