Set up tab completion for ssh and scp
Tab completion is a ubiqutious time-saver, and I use it everywhere I can.
Here’s how I set it up to autocomplete hostnames when I use the ssh
or
scp
commands.
With tab completion in place, I can just type:
$ ssh <tab>
And be presented with a list of known hosts in my ~/.ssh/known_hosts
file, or any hosts in my ~/.ssh/config
file.
$ ssh <tab>
alex
alex.petdance.com
birdie
bogey
bonilla
cacti
champ
etc etc etc
Like all tab completion, I can just type the first letter and <tab> and get a shortened list:
$ ssh g<tab>
git.petdance.com github.com gitlab.com
I had found an ssh
autocompletion script long ago, but it only took
hostnames from ~/.ssh/known_hosts
, and I wanted it to also include host
aliases from my ~/.ssh/config
file. I added the config file parsing, had
a little fight with the compgen
command, but now have it working.
Here’s the magic I had to add to my bash startup.
__complete_ssh_host() {
local KNOWN_FILE=~/.ssh/known_hosts
if [ -r $KNOWN_FILE ] ; then
local KNOWN_LIST=`cut -f 1 -d ' ' $KNOWN_FILE | cut -f 1 -d ',' | grep -v '^[0-9[]'`
fi
local CONFIG_FILE=~/.ssh/config
if [ -r $CONFIG_FILE ] ; then
local CONFIG_LIST=`awk '/^Host [A-Za-z]+/ {print $2}' $CONFIG_FILE`
fi
local PARTIAL_WORD="${COMP_WORDS[COMP_CWORD]}";
COMPREPLY=( $(compgen -W "$KNOWN_LIST$IFS$CONFIG_LIST" -- "$PARTIAL_WORD") )
return 0
}
complete -F __complete_ssh_host ssh
complete -f -F __complete_ssh_host scp
The first complete
line tells bash that whenever I type the ssh
command
and hit <tab> bash should run the function __complete_ssh_host
to
get a list of possible hosts to present as autocomplete targets.
The __complete_ssh_host
looks in the ~/.ssh/known_hosts
file to extract
all the non-IP hostnames it can find, and then looks in ~/.ssh/config
for
hostnames. Then, it passes those hostnames and the partial word you’ve
typed so far to the compgen
command.
compgen
takes a list of things that you could autocomplete, plus whatever
partial word you’ve already typed, and returns a list of valid
autocompletions. Try it from the shell prompt.
$ compgen -W 'aardvark apple baseball boogie cat' -- a
aardvark
apple
Here, I’m supplying a list of words, and then after the --
, the start of
a word, the letter a
. compgen
replies that the options that are
possible are aardvark
and apple
.
This compgen
was confusing, but now that I’ve figured out how to use it
correctly, it makes perfect sense. I wish that the bash manual had an
illustrative example like this one, which would have made everything
immediately clear. I hope that my example here will make it clear for
someone else.