Skip to content

Instantly share code, notes, and snippets.

@aliang
Created June 14, 2011 07:14
Show Gist options
  • Save aliang/1024466 to your computer and use it in GitHub Desktop.
Save aliang/1024466 to your computer and use it in GitHub Desktop.
Add auto complete to your ssh, put into your .bash_profile
_complete_ssh_hosts ()
{
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
comp_ssh_hosts=`cat ~/.ssh/known_hosts | \
cut -f 1 -d ' ' | \
sed -e s/,.*//g | \
grep -v ^# | \
uniq | \
grep -v "\[" ;
cat ~/.ssh/config | \
grep "^Host " | \
awk '{print $2}'
`
COMPREPLY=( $(compgen -W "${comp_ssh_hosts}" -- $cur))
return 0
}
complete -F _complete_ssh_hosts ssh
@baonq-me
Copy link

baonq-me commented Dec 6, 2022

It doesn't work for me, I get ~/.zprofile: command not found: complete

The same. MacOS Monterey 12.5.1

@Lat31320
Copy link

Lat31320 commented Mar 2, 2023

Thanks for this script.

I removed the known_hosts section because I want only the .ssh/config file to be parsed.

_complete_ssh_hosts ()
{
        COMPREPLY=()
        cur="${COMP_WORDS[COMP_CWORD]}"
        comp_ssh_hosts=`cat ~/.ssh/config | \
                         grep --color=never "^Host " | \
                         awk '{print $2}'
                   `
        COMPREPLY=( $(compgen -W "${comp_ssh_hosts}" -- $cur))
        return 0
}
complete -F _complete_ssh_hosts ssh

@timhughes
Copy link

timhughes commented Aug 1, 2023

It doesn't work for me, I get ~/.zprofile: command not found: complete

The same. MacOS Monterey 12.5.1

The script is written in bash. zsh has a different way of doing things.

Converted the searches to AWK so there is only 2 commands being called instead of 9 and it is easy to comment out one of the sources if you don't like it.

_complete_ssh_hosts ()
{
        COMPREPLY=()
        cur="${COMP_WORDS[COMP_CWORD]}"
        comp_ssh_hosts=`
            awk '{split($1,aliases,","); if (aliases[1] !~ /^\[/) print aliases[1]}' ~/.ssh/known_hosts ;
            awk '/^Host/ && $2 !~ /[*]/ {print $2}' ~/.ssh/config ;
            `
        COMPREPLY=( $(compgen -W "${comp_ssh_hosts}" -- $cur))
        return 0
}
complete -F _complete_ssh_hosts ssh

@michaelleb
Copy link

Actually, this can work for zsh as well, we just need to enable bash style autocomplete before using this function.
Here is complete example: put this inside ~/.zshrc

#### initialize completion system ####
# see https://unix.stackexchange.com/questions/593433/bash-like-autocompletion-for-ssh-command-in-zsh-shell-with-etc-hosts-file
# see https://zsh.sourceforge.io/Doc/Release/Completion-System.html
autoload -Uz compinit; compinit


# enable bash style autocomplete (requires compinit to be called before this)
# see https://stackoverflow.com/questions/3249432/can-a-bash-tab-completion-script-be-used-in-zsh
# see https://zsh.sourceforge.io/Doc/Release/Completion-System.html
autoload -Uz bashcompinit; bashcompinit


# replace the default ssh autocomplete that comes from compinit 
# with this _complete_ssh_hosts function which looks for hosts in ~/.ssh/config and ~/.ssh/known_hosts
# Note: requires bashcompinit to enable this bash style autocomplete function
# see https://stackoverflow.com/questions/52438964/mac-autocomplete-for-ssh-hosts-in-terminal
# see https://gist.github.com/aliang/1024466
_complete_ssh_hosts ()
{
        COMPREPLY=()
        cur="${COMP_WORDS[COMP_CWORD]}"
        comp_ssh_hosts=`
            awk '{split($1,aliases,","); if (aliases[1] !~ /^\[/) print aliases[1]}' ~/.ssh/known_hosts ;
            awk '/^Host/ && $2 !~ /[*]/ {print $2}' ~/.ssh/config ;
            `
        COMPREPLY=( $(compgen -W "${comp_ssh_hosts}" -- $cur))
        return 0
}
complete -F _complete_ssh_hosts ssh


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment