如何在bash中启用默认文件完成
假设我有一个名为“foo”的命令,它接受一个参数(“加密”或“解密”),然后是一个文件列表。我想编写一个bash完成脚本,帮助处理第一个参数,然后为其他参数启用标准文件完成。我能做的最接近的事情是:如何在bash中启用默认文件完成,bash,Bash,假设我有一个名为“foo”的命令,它接受一个参数(“加密”或“解密”),然后是一个文件列表。我想编写一个bash完成脚本,帮助处理第一个参数,然后为其他参数启用标准文件完成。我能做的最接近的事情是: complete -F _foo foo function _foo() { local cmds cur if [ $COMP_CWORD -eq 1 ] then cur="${COMP_WORDS[1]}" cmds=("encrypt
complete -F _foo foo
function _foo()
{
local cmds cur
if [ $COMP_CWORD -eq 1 ]
then
cur="${COMP_WORDS[1]}"
cmds=("encrypt decrypt")
COMPREPLY=($(compgen -W "${cmds}" -- ${cur}) )
else
COMPREPLY=($(compgen -f ${COMP_WORDS[${COMP_CWORD}]} ) )
fi
}
这将正确执行第一个参数,并将从当前目录中为后续参数选择一个文件名。但是假设当前目录包含一个子目录栏,其中包含一个文件baz.txt。键入ba TAB TAB后,完成结果为“bar”(在“r”后面的空格),并准备好选择下一个参数。我想要的是标准的bash完成,结果是“bar/”(斜杠后面没有空格),可以在子目录中选择一个文件。有没有办法做到这一点?bash文档可能有点神秘。最简单的解决方案是更改完成函数绑定:
complete -o filenames -F _foo foo
这意味着函数返回文件名(包括目录),并启用对结果的特殊处理
(我想说明的是,文档中没有明确说明,这可以有效地按照您的完成功能设置对进行全面的后置处理[]
;并且当应用于compgen
时,其中包含的一些-o
选项似乎没有任何效果。)
通过使用以下命令,可以更接近正常的bash行为:
complete -o filenames -o bashdefault -F _foo foo
这会让你重新完成
然而,上述方法存在两个问题:
- 如果您有一个名为“encrypt”或“decrypt”的目录,则关键字的扩展将增加一个尾随“/”
扩展将不起作用,$VARIABLE
将变为$
,以便更好地将文件名与\$
匹配。类似地,$
扩展也无法工作@host
compgen
输出,而不是依赖“文件名”后处理:
_foo()
{
local cmds cur ff
if (($COMP_CWORD == 1))
then
cur="${COMP_WORDS[1]}"
cmds="encrypt decrypt"
COMPREPLY=($(compgen -W "$cmds" -- "$cur"))
COMPREPLY=( "${COMPREPLY[@]/%/ }" ) # add trailing space to each
else
# get all matching files and directories
COMPREPLY=($(compgen -f -- "${COMP_WORDS[$COMP_CWORD]}"))
for ((ff=0; ff<${#COMPREPLY[@]}; ff++)); do
[[ -d ${COMPREPLY[$ff]} ]] && COMPREPLY[$ff]+='/'
[[ -f ${COMPREPLY[$ff]} ]] && COMPREPLY[$ff]+=' '
done
fi
}
complete -o bashdefault -o default -o nospace -F _foo foo
\u foo()
{
本地cmds cur ff
如果($COMP_CWORD==1))
然后
cur=“${COMP_WORDS[1]}”
cmds=“加密-解密”
COMPREPLY=($(compgen-W“$cmds”--“$cur”))
COMPREPLY=(“${COMPREPLY[@]/%/}”)#在每个
其他的
#获取所有匹配的文件和目录
COMPREPLY=($(compgen-f--“${COMP_WORDS[$COMP_CWORD]}”))
对于((ff=0;ff我知道这有点晚了,但我在这里找到了一个解决方案:
基本上,您可以使用complete-obashdefault-obashdault
,当您想要恢复到默认的bash完成时,您可以设置COMPREPLY=()
。下面是一个示例:
complete -o bashdefault -o default -F _foo foo
_foo() {
local cur=${COMP_WORDS[COMP_CWORD]}
if (( $COMP_CWORD == 1 )); then
COMPREPLY=( $(compgen -W 'encrypt decrypt' -- "$cur") )
else
COMPREPLY=()
fi
}
+1非常整洁。它恢复为readline默认值而不是bash,这并不是因为它会影响操作,而是您丢失了bash默认完成($,~,@)。我认为compopt-obashdefault
(bash-4.0)在这方面会有所帮助。${COMPREPLY[@]/%/}
添加了一个空格?bash是一种非常丑陋的语言。