Bash Auto-completion with Tab button doesn't complete at some condition

We know some commands doesn't work on some files/directories. As an example we cannot use "cd" command on a file and when we try to press tab button to complete our line, the system doesn't show us any file for completion.

But I encountered an interesting scenario when I try autocomplete feature to complete a file name that finish with ".a". I can explain this scenario like below:

[root@myserver multipath]# ls -1
idlist
idlist.a
idlist.b
multipath.a
multipath.sh

I have these files in a directory.

  • When I type "vim m" and then press the "tab" button the system auto-complete this command as "vim multipath.sh".
  • When I type "vim idlist" and then press the "tab" button the system show me two option: "idlist" and "idlist.b". There is no "idlist.a" option.
  • And finally, when I use "cat (or anything else)" the system show me files that finish with ".a" (with all options). There is no confusing something at there.

What is the secret behind of ".a"? Why the system does not complete this files when we use vi/vim command?


In my Kubuntu there is no /usr/share/bash-completion/completions/vim file, but the file

/usr/share/bash-completion/bash_completion

contains this line:

_install_xspec '*.@(o|so|so.!(conf|*/*)|a|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)' vi vim gvim rvim view rview rgvim rgview gview emacs xemacs sxemacs kate kwrite

Note there are lines for different tools, lots of them.

If I enable set -x and then vimtab, I see the pattern being used multiple times, finally even with an uppercase version of it, like this:

compgen -f -X '!!(*.@(o|so|so.!(conf|*/*)|a|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)|*.@(O|SO|SO.!(CONF|*/*)|A|[RS]PM|GIF|JP?(E)G|MP3|MP?(E)G|AVI|ASF|OGG|CLASS))' --

I temporarily removed |a from the bash_completion file. New instances of bash began to recognize *.a (and *.A) files.

I believe the pattern specifies files one wouldn't usually want to edit as text. This list (which is obviously case-insensitive) tells us a may denote a library in Unix. My guess is this is the reason to exclude it. Note o and so are other common extensions for binary files in Unix, they are also in the pattern.