Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Sometimes I need to quickly copy a file from my remote server to my local machine. Here's my current workflow:

  1. I SSH into my remote server, find the file and copy its full path.
  2. I open new terminal tab and type:

sftp user@hostname:/path/to/file (where /path/to/file is the path I previously copied)

It's not such a pain but it would be really nice if I could skip step 1 and find the path to the file using tab completion directly when typing the sftp command.

To illustrate, I could start typing sftp user@hostname:/ press TAB and get a listing of folders in /. I could then go on typing ho press TAB and it would auto-complete to home, etc. etc.

I'm not sure if such a feature exists and otherwise, is it theoretically possible to write a custom tab completion script as described? Any pointers on where to start?

share|improve this question
up vote 4 down vote accepted

Thanks to shellholic's answer, I was able to make it (somewhat) work for sftp. First, create the file /etc/bash_completion.d/sftp with the following content:

# custom sftp(1) based on scp
# see
    local configfile cur userhost path prefix

    cur=`_get_cword ":"`

    _expand || return 0

    if [[ "$cur" == *:* ]]; then
        local IFS=$'\t\n'
        # remove backslash escape from :
        # 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)
        # 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

    if [[ "$cur" = -F* ]]; then
        # 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}")"
                    [ "$1" ] && configfile="$(dequote "$1")"

        [[ "$cur" == */* ]] || _known_hosts_real -c -a -F "$configfile" "$cur"
    # 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

Then in bash you need to execute . /etc/bash_completion.d/sftp in order to load the script.

All I really did was copy/paste the scp completion script from /etc/bash_completion.d/ssh and replace scp occurences with sftp.

share|improve this answer

Don't use sftp, use scp and it work. You will need an ssh key.

share|improve this answer
Thanks, I was actually able to make it work for sftp using scp's auto completion's script. I'm trying to use sftp as much as possible as it is supposed to supersede scp. – Olivier Lalonde Nov 24 '10 at 2:42
you don't really need a key pair for scp, do you? – Nanne May 27 '13 at 6:28

Another alternative: use lftp instead, which has superb built in tab completion (but that'll be once you start it, not in the shell.) It can talk sftp and many other protocols.

share|improve this answer

I hear that a program called with-readline will allow the standard OpenSSH command line program sftp to utilize tab completion. I cannot verify that it works, but I've been wanting that same functionality for years now.

info on with-readline and sftp:

with-readline link:

Let me know how it works for you.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.