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