suppose I have following entry in my /etc/hosts      server1.mydomain.com

and I have a directory SERVER-FILES in current dir. I want to scp the directory SERVER-FILES somewhere. I type SE and use autocompletion to complete the directory name:

$ scp -rp SE<TAB>

This completion should be totally unambiguous. But zsh autocomplletion tries to be too smart, and treats hostnames case-insensitive, and thus attempts to match SE to hostnames:

$ scp -rp SE<TAB>

How can I disable this annoying feature, where zsh is trying to match hostnames case-insensitive, and therefore completes SE<TAB> toserver1.mydomain.com` ?

I have changed the following line in the ssh completion file Unix/_ssh:

- compadd -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' "$@" $config_hosts
+ compadd "$@" $config_hosts

but that did not help.

  • does this work for you? zstyle ':completion::complete:scp:*' hosts off – the_velour_fog Nov 13 '16 at 12:22
  • scp could complete either a filename or a hostname at that position, so matches both the directory and the hostname. – thrig Nov 13 '16 at 15:25
  • I am not trying to disable hostname completion. I just want to disable the nonsense feature of case insensitive hostname completion. – 400 the Cat Nov 14 '16 at 9:03
  • I think that you would have to write your own matcher for that. As said before, at this argument position both hosts and files are possible and zsh proposition seems correct. You could start typing your argument with ./SE to tell zsh that you mean a file. – Kalavan Nov 16 '16 at 7:53
  • @Kalavan - yes, at this argument position both hosts and files are possible. But there is no host matching SE. I want completion for both hostname and files, but I don't want to match hostnames case-insensitive. – 400 the Cat Nov 16 '16 at 8:01

I believe you are editing a wrong line.

AFAIK config_hosts in Unix/_ssh refers to the host entries in your ~./ssh/config, not /etc/hosts.

The completion rules for /etc/hosts are defined a bit earlier, in the following block:

# If users-hosts matches, we shouldn't complete anything else.
if [[ "$IPREFIX" == *@ ]]; then
  _combination -s '[:@]' my-accounts users-hosts "users=${IPREFIX/@}" hosts "$@" && return
  _combination -s '[:@]' my-accounts users-hosts \
    ${opt_args[-l]:+"users=${opt_args[-l]:q}"} hosts "$@" && return

but this in turn just reuses the hosts style defined in Unix/_hosts

So if you edit the compadd definition at the end of the Unix/_hosts file like this:

#_wanted hosts expl host \
#    compadd -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' -a "$@" - _hosts
_wanted hosts expl host \
     compadd -a "$@" - _hosts

you should get the behavior you want.


Please note that editing a system-wide completion files is not generally a very good practice, so you may want to just redefine hosts in your local ZSH config instead, e.g. by adding a function like that to your ~./zsh:

_hosts() { compadd $(getent hosts | tr -s ' ' '\t' | cut -f2) }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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