Optimal Location for User-Specific Bash Completion Scripts in Linux Without Root Access


3 views

When developing personal bash scripts with custom completion rules, system-wide installation in /etc/bash_completion.d/ isn't always practical or possible. Without root access, we need user-specific solutions that integrate cleanly with bash's completion system.

The bash completion ecosystem supports several user-space locations:

1. ~/.bash_completion (single file approach)
2. ~/.bash_completion.d/ (directory approach)
3. Direct sourcing from ~/.bashrc

Option 1: Single File Method

Create a ~/.bash_completion file and add this to your ~/.bashrc:

if [ -f ~/.bash_completion ]; then
    . ~/.bash_completion
fi

Option 2: Directory Method

Create a ~/.bash_completion.d/ directory and add this to ~/.bashrc:

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

Here's how to add custom git completions in your user space:

# ~/.bash_completion.d/git-custom
_git_myfeature() {
    local subcommands="start finish review"
    COMPREPLY=( $(compgen -W "$subcommands" -- "${COMP_WORDS[1]}") )
}
complete -F _git_myfeature git-myfeature
  • Prefix completion filenames with your username (e.g., ~/.bash_completion.d/jdoe_git)
  • Keep completion scripts modular - one per command/function
  • Test with bash --norc to ensure proper loading

If completions don't load:

# Check file permissions:
chmod +x ~/.bash_completion.d/*

# Verify sourcing order in .bashrc:
echo $BASH_COMPLETION_USER_DIR

When developing custom bash scripts with completion rules on a multi-user Linux system, you often face a dilemma: the standard /etc/bash_completion.d/ location requires root access, while your completion rules should only apply to your user session. This becomes particularly relevant in corporate environments or shared hosting where you lack administrative privileges.

Most developers initially consider these approaches:

1. Directly sourcing from .bashrc:
   source ~/.bash_completion.myscript

2. Creating a custom directory:
   mkdir -p ~/.bash_completion.d/

While functional, these methods lack standardization and may cause maintenance issues when managing multiple completion scripts.

The most elegant approach follows the XDG Base Directory Specification while maintaining compatibility:

# Create the directory if it doesn't exist
mkdir -p ~/.local/share/bash-completion/completions

# Add this to your .bashrc
if [ -d ~/.local/share/bash-completion/completions ]; then
    for f in ~/.local/share/bash-completion/completions/*; do
        [ -f "$f" ] && source "$f"
    done
done

For a script named mycli, here's how to implement proper completion:

# Save as ~/.local/share/bash-completion/completions/mycli
_mycli_completion() {
    local cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=( $(compgen -W "start stop restart status" -- "$cur") )
}
complete -F _mycli_completion mycli

For complex environments, consider these enhancements:

# Lazy-loading completions
if command -v mycli &>/dev/null; then
    source ~/.local/share/bash-completion/completions/mycli
fi

# Version-controlled completions
git init ~/.local/share/bash-completion

This solution works across most modern Linux distributions including:

  • Debian/Ubuntu (with bash-completion package)
  • RHEL/CentOS
  • openSUSE
  • Arch Linux