Bash – Make Bash Tab Autocomplete match like “Contains” in all possible files instead of “Starting With”

autocompletebashcommand lineshellzsh

I want to make the bash autocomplete on TAB behave a little like oh-my-zsh.

I already added ignore case and cycle through all possibilities on each tab.

Now currently if I have a folder in directory named LinuxCommands and I write Comm+TAB it doesn't match LinuxCommands folder.

Is there any way to change the behavior of bash to match the keyword entered with folder and file names based on "filename contains keywords" instead of the current behavior "filename starts with keywords"?

I don't think it matters as it's all bash. But just in case it does, I'm using MacOS Sierra.

Update 1

Currently I have this code in my ~/.bashrc for this modification

    _cd_completion() {
        mapfile -t COMPREPLY < <(ls -d */ | grep "${COMP_WORDS[COMP_CWORD]}")
    }
    complete -F _cd_completion cd

    # If ~./inputrc doesn't exist yet, first include the original /etc/inputrc so we don't override it
    if [ ! -a ~/.inputrc ]; then echo '$include /etc/inputrc' > ~/.inputrc; fi
    # Add option to ~/.inputrc to enable case-insensitive tab completion
    bind 'set completion-ignore-case On'

    bind 'set show-all-if-ambiguous on'
    bind 'TAB:menu-complete'

It accomplishes the tasks individually. But the integral performance is weird. It autocompletes and then cycles through the contents of the same folder after autocompleting which is one level behind on directory.

Ex: if I have Folder1, Something2 and NewFolder3 and if I press cd F+TAB then it shows > cd Folder1/ and then when I press TAB again, it shows > cd Folder1/Something2 and the next time shows > cd Folder1/NewFolder3 and keeps cycling through the previous level folders like this.

Best Answer

You can add your own bash_completion rules in ~/.bashrc add the folowing code to the file:

_cd_completion() {
    mapfile -t COMPREPLY < <(ls -d */ | grep "${COMP_WORDS[COMP_CWORD]}")
}
complete -F _cd_completion cd

next you have to restart your terminal or enter the next command: source ~/.bashrc

If you want to make it system-wide you can also add the rules to bash_completion inside the file /usr/share/bash-completion/completions/cd

Related Question