3

Suppose I wish to export an environment variable named MYPATH holding following 2 paths:

  1. /full/path/to/fileA
  2. /another/full/path/to/fileB

So, I think it should be done like this in bash:

$export MYPATH=/full/path/to/fileA:/another/full/path/to/fileB

The issue I'm facing is auto-complete (Tab key) works while writing path A in command, but after : auto-complete stops working, so it is difficult to write path B in the console in absence of auto-complete.

Surprisingly, it works if:

  • I use semi-colon instead of colon, but that's not correct path separator anyway.
  • I am root user.

Can someone please explain the reason for this behavior?

  • Bash version: GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
  • Bash-completion version: all/xenial-updates 1:2.1-4.2ubuntu1.1
  • OS version: Ubuntu 16.04.6 LTS
  • 2
    Is bash-completion installed on your system? I'm getting some inconsistent behavior on the systems I can test with, depending on bash-completion's version. With bash-completion not sourced/not installed, completion of export mypath=/path/1:/path/2 works (even after any :) on various Bash versions -- I don't have any Bash 4.3, though. – fra-san Aug 21 '19 at 14:20
  • @fra-san I do have /etc/profile.d/bash_completion.sh in my system (Ubuntu 16.04), but I'm not sure if it is having any effect, I didn't install it manually or I didn't made changes around this area, using default OS settings. Could you reprodue the issue on any of your systems? – Sagar Gupta Aug 21 '19 at 14:47
  • 3
    Yes, I can reproduce the behavior you described with bash-completion 2.9; with version 2.1 I get no completion at all for export myvar=; with version 1.3, export mypath=/path/1:/path/2 has working auto-completion for /path/2, too. Please, add your bash-completion (and operating system) version to your question. – fra-san Aug 21 '19 at 15:12
2

The behavior you describe is likely caused by bash-completion.

(What follows is based on the current version of the package (2.9), but it will be reasonably accurate for the 2.1 version you have too).

bash-completion provides a set of completion specifications (compspec) that the Readline library uses to complete words that are supplied as arguments to commands in Bash. They are defined using the complete builtin command, usually in the form:

complete -F function command

For the export builtin, the function _export is defined in /usr/share/bash-completion/completions/export.

When the word to complete includes (or ends in) a =, _export tries to complete it (the part to the right of the first =, actually) as a file or directory name; when the word to complete does not include a =, it tries to complete it as a variable name. Since the Readline library starts a new completion every time it runs across one of the characters listed in the COMP_WORDBREAKS variable (unless the character is escaped), which usually includes :, completion stops working after the first colon you append to a variable's value because, at that point, the word to complete is not including (or ending in) a = anymore.
(Note, incidentally, that file/directory name completion starts working again if you write export myvar=/usr/:othervar= and hit Tab).

bash-completion indeed has its own mechanism for handling special cases. For instance, : is correctly dealt with by the compspec for scp, which interprets what is on the right hand of a colon as a remote path. The same is not applied to export, though.

Readline's default behavior, which is triggered when a compspec for the current command is not found, is ultimately to attempt filename completion. That is why completion of path2 in export var=/path1/:/path2/ works when bash-completion is not installed or otherwise disabled (remember that every colon starts a new completion).

What can you do, then? You have some alternatives:

  1. File a feature request to bash-completion on GitHub.

  2. Define your own completion function for export.
    First, copy the compspec to the user completion file (which likely doesn't exist yet):

    $ cat /usr/share/bash-completion/completions/export >>~/.bash_completion
    

    Then edit ~/.bash_completion, changing complete -F _export export into complete -F _export -o default export. This instructs Readline to attempt the default completion when export's specific compspec gives no results.

  3. Use the default completion, instead of the one provided by bash-completion.
    Add to your ~/.bashrc:

    complete -o default -o bashdefault export
    

    (Suggestion from bash-completion's FAQ). The downside is that you lose the ability to complete variable names and export options.

  4. If you are willing to become familiar enough with bash-completion, define your own _export function, as in (2), by editing the provided one to let it handle : specially.

  • 1
    Thanks for the detailed answer! That also explains why it is working for the root user because, there, default completion is in effect on my system. – Sagar Gupta Aug 26 '19 at 11:10
  • 1
    @SagarGuptaFTW Yes -- I thought it could be like that, but I couldn't actually check/test that bit; so I left it out of my answer. Glad it helped. – fra-san Aug 26 '19 at 11:13

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.