Standard place for user defined bash_completion.d scripts?

Solution 1:

For non-XDG environments and bash-completion <= 2.8

Here is how a local user can have a working ~/.bash_completion.d/ directory.

  1. edit file: nano ~/.bash_completion, add the following:
for bcfile in ~/.bash_completion.d/* ; do
  . $bcfile
done
  1. make directory: mkdir ~/.bash_completion.d
  2. edit file: ~/.bash_completion.d/myscript, add the following:
_myscript_tab_complete () {
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    words="-f -h --etc"

    COMPREPLY=( $(compgen -W "${words}" -- ${cur}) )
    return 0
}
complete -F _myscript_tab_complete myscript
  1. source .bash_completion: . ~/.bash_completion

anticipating empty ~/.bash_completion.d/ directory

If you anticipate having an empty ~/.bash_completion.d/ directory, and want to avoid seeing the error message bash: /home/<username>/.bash_completion.d/*: No such file or directory, add a file type test with [ -f "$bcfile" ].

for bcfile in ~/.bash_completion.d/* ; do
  [ -f "$bcfile" ] && . $bcfile
done

For XDG environments & bash-completion <= version 2.8

(To see your version: rpm -qa | grep bash-completion)

Note that bash-completion 2.8 README documentation still recommends ~/.bash_completion, See https://github.com/scop/bash-completion/tree/2.8

You know your linux environment is XDG if xdg-usr-dir command exists and returns your home directory, and your environment variables include XDG_*; execute: env | grep XDG.

For XDG environment & bash-completion >= version 2.9

According to the bash-completion README starting in version 2.9 https://github.com/scop/bash-completion/tree/2.9 (April 27, 2019) there is now recognized a working local user bash_completion directory. Additionally an alternate bash_completion config file has already been supported for several previous releases.

  • ~/.bash_completion.d -> ${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion
  • ~/.bash_completion -> ${XDG_CONFIG_HOME:-$HOME/.config}/bash_completion

To implement with this configuration, complete the previous steps 3,4 above using $XDG_DATA_HOME/bash-completion - you should not modify $XDG_CONFIG_HOME/bash_completion as described in step 1, but you may need to create the $XDG_DATA_HOME/bash-completion directory.

Note: As of CentOS 8.2 and Fedora 32, bash-completion <= 2.8 is installed.

Solution 2:

Use a ~/.bash_completion file.

From the Bash Completion FAQ:

Q. How can I insert my own local completions without having to
reinsert them every time you issue a new release?

A. Put them in ~/.bash_completion, which is parsed at the end of the
main completion script. See also the next question.

Q. I author/maintain package X and would like to maintain my own
completion code for this package. Where should I put it to be sure
that interactive bash shells will find it and source it?

A. Install it in one of the directories pointed to by
bash-completion's pkgconfig file variables. There are two
alternatives: the recommended one is 'completionsdir' (get it with
"pkg-config --variable=completionsdir bash-completion") from which
completions are loaded on demand based on invoked commands' names,
so be sure to name your completion file accordingly, and to include
for example symbolic links in case the file provides completions
for more than one command. The other one which is present for
backwards compatibility reasons is 'compatdir' (get it with
"pkg-config --variable=compatdir bash-completion") from which files
are loaded when bash_completion is loaded.


Solution 3:

The FAQ has been updated. There is now a standard place for local completions.

Q. Where should I install my own local completions?

A. Put them in the completions subdir of $BASH_COMPLETION_USER_DIR (defaults to $XDG_DATA_HOME/bash-completion or ~/.local/share/bash-completion if $XDG_DATA_HOME is not set) to have them loaded on demand. See also the next question's answer for considerations for these files' names, they apply here as well. Alternatively, you can write them directly in ~/.bash_completion which is loaded eagerly by our main script.

  1. If it does not exist, create a directory at ~/.local/share/bash-completion/completions (or $XDG_DATA_HOME/bash-completion/completions).
$ mkdir -p ~/.local/share/bash-completion/completions
  1. Put your completions in the new directory.
$ cp <your_completions_file> ~/.local/share/bash-completion/completions

Note the that completions file should have the same name as the command that it is providing completions for. (e.g. The completions file for git should be called "git".)


Solution 4:

At least bash-completion 2.8 and later enable option to place local Bash completions in directory

${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions

The completion file names or symbolic link names must match the respective command names. These completions are loaded only on demand. Completions stored in file ~/.bash_completion are loaded always.

Reference: See "Q. Where should I install my own local completions?" in https://github.com/scop/bash-completion/blob/master/README.md


Solution 5:

A simpler solution is to use the nullglob option. While this isn't portable, neither are bash completions. So portability doesn't matter.

Also, you'll want to use quotes around the variable when sourcing. This handles the case where the file has spaces other other special characters.

shopt -s nullglob

for f in ~/.bash_completion.d/*; do
  [ -f "$f" ] && . "$f"
done