Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

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

I found the following script (for bash) that enables me to get tab completion for any hostname I've connected to (from ~/.ssh/known_hosts):

complete -W "$(echo `cat ~/.ssh/known_hosts | cut -f 1 -d ' ' | sed -e s/,.*//g | uniq | grep -v "\["`;)" ssh

However, the problem is that the tab completion doesn't work after I've typed a username.

How can I improve this so if I type...

ssh myusername@my 

and expect it to complete "myhostname.com" it will be able to do so?

It would be even better if it could tab whole strings (user@hostname) as well, but I can live with either option. Without the first, this isn't much use unless my host username matches the local username.

share|improve this question
Haven't we all learned in school to frown upon backticks, unless visiting a Unix museum, and that $() can be nested?! :) Still +1 – 0xC0000022L Sep 12 '13 at 18:40
@0xC0000022L Eek, sorry, I was much newer at bash when I wrote this question. – NickC Sep 12 '13 at 19:51

The known_hosts file by default usually contains hashed entries which bash_completion can't parse.

You can edit your ssh_config (/etc/ssh/ssh_config) to set:

HashKnownHosts no

Then you'll probably need to clear your current known hosts file:

> ~/.ssh/known_hosts
share|improve this answer

If $COMP_WORDBREAKS contains "@" (that is the default on my system) then serious problems arise which I could not solve (after pressing Tab and Enter one "@" was removed).

But if you delete it from that environment variable then this works:

_foo () {
  if [[ "$COMP_WORDBREAKS" =~ "@" ]]; then
    echo ""
    echo '$COMP_WORDBREAKS contains "@"; aborting'
    if [[ ${COMP_WORDS[COMP_CWORD]} =~ "@" ]]; then
    COMPREPLY=($(cut -f 1 -d ' ' <~/.ssh/known_hosts |
      sed -e 's/,/\n/g' | uniq |
      awk -v prefix="${prefix}" '/\[/ {next}; {print prefix $0;}'))
    COMPREPLY=($(compgen -W "${COMPREPLY[*]}" "${COMP_WORDS[COMP_CWORD]}"))

complete -F _foo ssh
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.