3

I'm regularly downloading files from a remote server, always from the same directory. So I wrote a custom function that I put in my bashrc:

download_from_myserver () {
    for file in "$@"
    do
        rsync myserver:/home/pierre/downloads/"$file" .
    done
}

Right now, the autocompletion works by default with files in the current directory. I would like to change the autocompletion so that bash automatically connects to the server via ssh and autocompletes with files that are in myserver:/home/pierre/downloads/.

In case I'm not being clear, here's an example: let's say I have my_file.txt in the remote directory, I want to be able to do this:

download_from_my_server my_fiTAB
download_from_my_server my_file.txt

How would I do this ?

Notes : I'm already using a password-less connection, rsync and scp autocomplete work well, that's not the issue. I'm using Ubuntu on both machines if that's important.

1
  • Nit: in "$@" is redundant in this case - for by default loops over the parameters.
    – l0b0
    May 15, 2013 at 10:55

1 Answer 1

3

Edit: Sliced it up some more.

You might find this useful, from Debian Administration: An introduction to bash completion.


Complete script: /some/location/my_ssh_autocomplete_script (only meant as a short starter):

#!/bin/bash

_get_rsync_file_list()
{
    # For test:
    #local -a flist=("foo" "bar")
    #printf "%s " "${flist[@]}"
    # Or:
    ls /tmp
    
    # For live something in direction of:
    #ssh user@host 'ls /path/to/dir' <-- but not ls for other then dirty testing.
}

_GetOptSSH()
{
    local cur

    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"

    case "$cur" in
    -*)
        COMPREPLY=( $( compgen -W '-h --help' -- "$cur" ) );;
    *)
        # This could be done nicer I guess:
        COMPREPLY=( $( compgen -W "$(_get_rsync_file_list)" -- "$cur" ) );;
    esac

    return 0
}

Download script /some/location/my_ssh_download_script:

#!/bin/bash

server="myserver"
path="/home/pierre/downloads"

download_from_myserver() {
    for file; do
        rsync "$server:$path/$file"
    done
}

case "$1" in
    "-h"|"--help")
        echo "Download files from '$server', path: '$path'" >&2
        exit 0;;
esac

download_from_myserver "$@"

In .bash_aliases:

alias download_from_myserver='/some/location/my_ssh_download_script'

In .bash_completion:

# Source complete script:
if . "/some/location/my_ssh_autocomplete_script" >/dev/null 2>&1; then
    # Add complete function to download alias:
    complete -F _GetOptSSH download_from_myserver
fi
4
  • "Double quote" every expansion, and anything that could contain a special character, eg. "$var", "$@", "${array[@]}", "$(command)". Use 'single quotes' to make something literal, eg. 'Costs $5 USD'. See <mywiki.wooledge.org/Quotes>, <mywiki.wooledge.org/Arguments> and <wiki.bash-hackers.org/syntax/words>. May 15, 2013 at 11:56
  • ls is a tool for interactively looking at file information. Its output is formatted for humans and will cause bugs in scripts. Use globs or find instead. Understand why: mywiki.wooledge.org/ParsingLs May 15, 2013 at 11:57
  • By convention, environment variables (PATH, EDITOR, SHELL, ...) and internal shell variables (BASH_VERSION, RANDOM, ...) are fully capitalized. All other variable names should be lowercase. Since variable names are case-sensitive, this convention avoids accidentally overriding environmental and internal variables. May 15, 2013 at 11:57
  • Thanks, this solution works really well! I did use find instead of ls, as pointed out by Rany Albeg Wein but that's the only thing I changed. And thank you for the link to debian-administration.org, I already read it but I wasn't handy enough to make good use of it :p May 15, 2013 at 12:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .