4

我添加了一个新的 alias scp_using_rsync,它使用 rsync 通过某些选项通过 SSH 复制文件。我想将 scp 的 bash 完成链接到这个别名。

当我添加这一行时它起作用:

complete -o bashdefault -o default -o nospace -F _scp scp_using_rsync 2>/dev/null || complete -o default -o nospace -F _scp scp_using_rsync

唯一的问题是我注意到,_scp只有在我在该 shell 中尝试使用 ssh/scp 至少一次完成制表符之后,才在我的 bash 环境中定义。所以如果我直接scp_using_rsync在一个新的 shell 中运行,我会得到_scpnot found 错误。

在尝试 ssh 或 scp 命令的 tab 补全之前和之后的新 shell 中的输出typeset -F清楚地表明,在第一次尝试 tab 补全之后定义了以下函数:

$ diff ~/.scratch/file1 ~/.scratch/file2
224a225,227
> declare -f _scp
> declare -f _scp_local_files
> declare -f _scp_remote_files
226a230
> declare -f _sftp
230a235,240
> declare -f _ssh
> declare -f _ssh_ciphers
> declare -f _ssh_macs
> declare -f _ssh_options
> declare -f _ssh_suboption
> declare -f _ssh_suboption_check

这些功能似乎是/usr/share/bash-completion/completions/ssh在我的系统中定义的。

这些是我的两个相互关联的问题:

  • 第一次尝试完成时,bash 如何确定在哪里自动获取定义并定义它们?
  • 我应该如何scp_using_rsync以类似的方式将 bash-completion for 链接到 scp 的 bash 完成?
4

3 回答 3

6

Bash 4.1为和增加了一个新-D选项:completecompgencompopt

新的 complete/compgen/compopt -D 选项,用于定义“默认”完成: 在未定义完成的命令上调用的完成。如果此函数返回124,则再次尝试可编程完成,允许用户在尝试完成时动态构建一组完成 ,方法是让默认完成函数在每次调用时安装单独的完成函数。

bash手册中有一个例子:

_completion_loader()
{
     . "/etc/bash_completion.d/$1.sh" >/dev/null 2>&1 && return 124
}
complete -D -F _completion_loader
于 2013-04-07T05:00:10.500 回答
3

我在应用 whjm 的答案时遇到了问题。_completion_loader正如 Tuxdude 注意到的,在我的发行版(Ubuntu 14.04)中已经定义了一个函数。函数定义如下:

_completion_loader () 
{ 
    local compfile=./completions;
    [[ $BASH_SOURCE == */* ]] && compfile="${BASH_SOURCE%/*}/completions";
    compfile+="/${1##*/}";
    [[ -f "$compfile" ]] && . "$compfile" &> /dev/null && return 124;
    complete -F _minimal "$1" && return 124
}

我想将完成的维护工作全部集中在一个地方,所以我添加了一个文件,/usr/share/bash-completion/completions/其中包含我想要为其添加完成的命令的名称。对于您的情况,您可以添加一个名为的文件,scp_using_rsync其中包含以下内容:

cfile="${compfile%/*}/scp"
cmd="${1##*/}"
. "$cfile" 
complete -F _scp $cmd

这将获取定义完成的文件scp,包括_scp函数,然后为您的命令添加完成。我觉得这是一种更直接和一致的方式(当然要这样做,您必须同意为所有用户更改此行为。)

于 2014-05-19T22:38:40.293 回答
0

一些完成函数是动态加载的。您可以手动加载它们,以便它们可以使用别名。例如,您可以将其添加到您的~/.bashrc,以便完成将与您的别名一起使用。

_completion_loader docker

于 2018-07-26T22:53:34.647 回答