53

I have user access (no root) into a Linux (Suse) machine where I developed some bash scripts and the corresponding bash autocompletion rules.

Since the scripts belong only to my user and therefore I need the complete rules only "active" for me (a part from the fact that I have no root write acces), placing my bash_completion script into /etc/bash_completion.d/ folder is not an option.

At the moment I named my file .bash_completion.myscript and source it directly from my .bashrc, but I just wonder if there is any other "standard" way of achieving these results, already considered in the bash implementation.

For example, creating a folder /home/myuser/.bash_completion.d/?

39

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.

| improve this answer | |
  • I googled and searched a lot inside serverfault before asking, but didn't think about the most basic step: RTFM! Many thanks for the response! – Carles Sala May 10 '13 at 18:18
  • 4
    Might want to specify that .bash_completion is a file and not a directory. Since bash_completion.d is a directory I assumed I could just scp my local bash_completion.d and rename it on the remote server, but on the next login it told me it had to be a file. – NobleUplift Nov 2 '16 at 18:41
  • 3
    @NobleUplift Bash Completion FAQ has changed and now contains information about a way for loading the user's Bash completions from a directory on demand. This seems to work by bash-completion version 2.8 at least, but not by 2.1. The files in the directory should be named exactly like the command they are for, or symbolic links could be used for that purpose. – jarno Jan 20 '19 at 12:06
  • @jarno I coded bash completion scripts for all the custom programs and scripts in our system but my senior developers shot them down :( – NobleUplift Jan 21 '19 at 17:47
  • @NobleUplift why? You can use them for yourself anyway. – jarno Jan 26 '19 at 14:18
56

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
    
  2. make directory: mkdir ~/.bash_completion.d

  3. 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
    
  4. source .bash_completion: . ~/.bash_completion

Update

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
| improve this answer | |
3

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

| improve this answer | |
2

The answer by Russell E Glaue is great but its ~/.bash_completion is incomplete.

The problem is when ~/.bash_completion.d/ is empty and subsequently for f in ~/.bash_completion.d/* prints the following error message:

-bash: /home/user/.bash_completion.d/*: No such file or directory

The simplest, portable solution is to skip the loop if the directory is empty:

if [[ -d ~/.bash_completion.d/ ]] && \
   ! find ~/.bash_completion.d/. ! -name . -prune -exec false {} +
then
    for f in ~/.bash_completion.d/*
    do
        source "$f"
    done
fi
| improve this answer | |
2

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
| improve this answer | |
  • 1
    FYI, an explanation of (or link to docs) about something being shown (i.e. nullglob) is helpful to the reader. – Cometsong Feb 25 '19 at 20:08
1

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".)

| improve this answer | |

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.