可以使用sftp获得制表符完成功能吗?


15

有时,我需要快速将文件从远程服务器复制到本地计算机。这是我当前的工作流程:

  1. 我通过SSH进入我的远程服务器,找到文件并复制其完整路径。
  2. 我打开新的终端标签并输入:

sftp user@hostname:/path/to/file (其中/ path / to / file是我先前复制的路径)

并不是很麻烦,但是如果我可以跳过步骤1并在键入sftp命令时直接使用制表符补全找到文件的路径,那将非常好。

为了说明这一点,我可以开始输入sftp user@hostname:/press TAB并获得/中的文件夹列表。然后,我可以继续ho按印刷机TAB,它将自动完成到home,等等。

我不确定是否存在这样的功能,否则从理论上讲可以编写描述的自定义制表符完成脚本吗?任何从哪里开始的指针?

Answers:


7

多亏了shellholic的回答,我才能够使它(某种程度上)适用于sftp。首先,创建/etc/bash_completion.d/sftp具有以下内容的文件:

# custom sftp(1) based on scp
# see http://askubuntu.com/questions/14645/is-it-possible-to-get-tab-completion-with-sftp
#
_sftp()
{
    local configfile cur userhost path prefix

    COMPREPLY=()
    cur=`_get_cword ":"`

    _expand || return 0

    if [[ "$cur" == *:* ]]; then
        local IFS=$'\t\n'
        # remove backslash escape from :
        cur=${cur/\\:/:}
        userhost=${cur%%?(\\):*}
        path=${cur#*:}
        # unescape spaces
        path=${path//\\\\\\\\ / }
        if [ -z "$path" ]; then
            # default to home dir of specified user on remote host
            path=$(ssh -o 'Batchmode yes' $userhost pwd 2>/dev/null)
        fi
        # escape spaces; remove executables, aliases, pipes and sockets;
        # add space at end of file names
        COMPREPLY=( $( ssh -o 'Batchmode yes' $userhost \
            command ls -aF1d "$path*" 2>/dev/null | \
            sed -e "s/[][(){}<>\",:;^&\!$=?\`|\\ ']/\\\\\\\\\\\\&/g" \
            -e 's/[*@|=]$//g' -e 's/[^\/]$/& /g' ) )
        return 0
    fi

    if [[ "$cur" = -F* ]]; then
        cur=${cur#-F}
        prefix=-F
    else
        # Search COMP_WORDS for '-F configfile' or '-Fconfigfile' argument
        set -- "${COMP_WORDS[@]}"
        while [ $# -gt 0 ]; do
            if [ "${1:0:2}" = -F ]; then
                if [ ${#1} -gt 2 ]; then
                    configfile="$(dequote "${1:2}")"
                else
                    shift
                    [ "$1" ] && configfile="$(dequote "$1")"
                fi
                break
            fi
            shift
        done

        [[ "$cur" == */* ]] || _known_hosts_real -c -a -F "$configfile" "$cur"
    fi
    # This approach is used instead of _filedir to get a space appended
    # after local file/dir completions, and $nospace retained for others.
    local IFS=$'\t\n'
    COMPREPLY=( "${COMPREPLY[@]}" $( command ls -aF1d $cur* 2>/dev/null | sed \
        -e "s/[][(){}<>\",:;^&\!$=?\`|\\ ']/\\\\&/g" \
        -e 's/[*@|=]$//g' -e 's/[^\/]$/& /g' -e "s/^/$prefix/") )

    return 0
}
complete -o nospace -F _sftp sftp

然后在bash中,您需要执行. /etc/bash_completion.d/sftp才能加载脚本。

我真正要做的只是从中复制/粘贴scp完成脚本,/etc/bash_completion.d/ssh并用sftp替换scp出现的事件。


4

另一种选择:使用lftp替代方法,它具有出色的内置制表符补全功能(但是一旦您启动它就可以了,而不必在外壳中启动。)它可以使用sftp和许多其他协议。


2

不要使用sftp,使用scp它就可以了。您将需要一个ssh密钥。


谢谢,实际上我可以使用scp的自动完成脚本将其用于sftp。我正在尝试尽可能多地使用sftp,因为它应该取代scp。
Olivier Lalonde 2010年

您真的不需要scp的密钥对,对吗?
娜妮

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.