40

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/?

33

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.

  • 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
  • 2
    @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 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 at 17:47
  • @NobleUplift why? You can use them for yourself anyway. – jarno Jan 26 at 14:18
43

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
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
1

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

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

${BASH_COMPLETION_USER_DIR-~/.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

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.