1

Auto-completing filenames (by pressing TAB after first characters of the filenames have been written) is case-sensitive both on my Ubuntu 13.04 box and on my Debian Squeeze box, when I use scp.

I have the following line in my .inputrc:

set completion-ignore-case on

and the case-insensitive autocompletion works fine on other shell programs.

Examples

<TAB> here means pressing the TAB key.

Correct behaviour

Currently, case-insensitive autocompletion works correctly on other shell programs, such as cp here:

$ cp my<TAB>

which yields, as expected:

$ cp MyFile

Incorrect behaviour

When using scp, the case-insensitive autocompletion doesn't work. On this line, nothing happens:

$ scp my<TAB>

And I have to revert to using the tedious case-sensitive autocompletion, like here:

$ scp My<TAB>

which yields, as expected:

$ scp MyFile

Possible workaround

Since this is a "recent" issue (i.e. this has been happening only for a few years or so), my guess is that this has something to do with the way some programs have autocompletable switches and other arguments, starting from some version of bash, but I'm unable to find out how to fix this specific problem.

2
  • I'm a little confused by your question. You mention SCP and tab completion, but in general, tab completion is handled locally. Can you clarify where you're expecting tab completion to be case-insensitive, and where it currently is and is not case sensitive?
    – ernie
    Sep 17, 2013 at 18:30
  • @ernie: I added some examples.
    – miikkas
    Sep 17, 2013 at 19:00

1 Answer 1

5

Debian (and Ubuntu) install provide you with a mountain of shell completion functions (in the bash-completion package); the functions are stored in the directory /etc/bash_completion.d and the one you're interested in is /etc/bash_completion.d/ssh.

As far as I can see, the way that script gets the list of possible completions is to issue the command ls -aFld ${path}*, where ${path} is the word which needs completing, either on the remote machine -- using ssh -- or directly on the local machine.

In order for this to work in a case-insensitive manner, you need to arrange for the glob in that ls command executing on the remote system to be expanded case-insensitively, which means you want to shopt -s nocaseglob before the ls command is executed.

I think your ubuntu/debian are more recent than mine, but it's possible that the following patch will work on your system. Otherwise, you can probably figure out the necessary edit:

--- ssh.old     2013-09-17 16:07:38.000000000 -0500
+++ ssh         2013-09-17 16:06:25.000000000 -0500
@@ -275,3 +275,3 @@
         files=$( ssh -o 'Batchmode yes' $userhost \
-            command ls -aF1d "$path*" 2>/dev/null | \
+            builtin shopt -s nocaseglob ';' command ls -aF1d "$path*" 2>/dev/null | \
             sed -e 's/'$_scp_path_esc'/\\\\\\&/g' -e '/[^\/]$/d' )
@@ -281,3 +281,3 @@
         files=$( ssh -o 'Batchmode yes' $userhost \
-            command ls -aF1d "$path*" 2>/dev/null | \
+            builtin shopt -s nocaseglob ';' command ls -aF1d "$path*" 2>/dev/null | \
             sed -e 's/'$_scp_path_esc'/\\\\\\&/g' -e 's/[*@|=]$//g' \
@@ -303,6 +303,6 @@
     if $dirsonly ; then
-        COMPREPLY=( "${COMPREPLY[@]}" $( command ls -aF1d $cur* 2>/dev/null | \
+        COMPREPLY=( "${COMPREPLY[@]}" $( shopt -s nocaseglob; command ls -aF1d $cur* 2>/dev/null | \
             sed -e "s/$_scp_path_esc/\\\\&/g" -e '/[^\/]$/d' -e "s/^/$1/") )
     else
-        COMPREPLY=( "${COMPREPLY[@]}" $( command ls -aF1d $cur* 2>/dev/null | \
+        COMPREPLY=( "${COMPREPLY[@]}" $( shopt -s nocaseglob; command ls -aF1d $cur* 2>/dev/null | \
             sed -e "s/$_scp_path_esc/\\\\&/g" -e 's/[*@|=]$//g' \
10
  • scp does not do completion for items on the remote machine . . .
    – ernie
    Sep 17, 2013 at 20:28
  • @ernie: scp doesn't, no. A bash script does (if you have it installed).
    – rici
    Sep 17, 2013 at 20:34
  • I had started writing an answer along the same lines but then found that I had no /etc/bash_completion/ssh (or anything else that could be relevant, like scp) on my Debian (LMDE) and yet can reproduce the OP's symptoms. If you have a /etc/bash_completion/ssh, which distribution are you using? I think this is something different and scp does a different type of completion since it also bring out names from the /etc/hosts file. +1 anyway for a good answer!
    – terdon
    Sep 18, 2013 at 3:37
  • @terdon: it's /etc/bash_completion.d/ssh and I'm using Ubuntu 12.04. It's a debian package called bash-completion. I don't know what other mechanism your distro would have, but the completions functions are visible if you type set, so you can probably find where they're being loaded from. I found a function called _known_hosts_real in /etc/bash_completion which looks through various ssh config files for known hosts, but bash knows how to look through /etc/hosts already: try compgen -A hostname
    – rici
    Sep 18, 2013 at 5:02
  • The file I had to edit on Ubuntu 13.04 was /usr/share/bash-completion/completions/scp, after which your suggestion worked like a charm. Thanks for the great answer!
    – miikkas
    Sep 18, 2013 at 11:20

You must log in to answer this question.

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