如何使 bash 选项卡完成表现得像 vim 选项卡完成并循环匹配?

多年来我一直想找到解决办法。

由于这个原因,在 Vim 中操作文件比 bash 更有效率。

如果有的话

file_12390983421
file_12391983421
file_12340983421
file_12390986421

在 bash 和 type file _ 1-> tab 中,它显然列出了:

file_12390983421 file_12391983421 file_12340983421 file_12390986421

这是一个可怕的无聊和痛苦的工作。

Vim 中的相同序列将一次循环一个文件。

有人能告诉我如何在 bash 中做到这一点,或者如果还有其他 shell 可以做到这一点,我明天就换。

28460 次浏览

By default TAB is bound to the complete readline command. Your desired behavior would be menu-complete instead. You can change your readlines settings by editing ~/.inputrc. To rebind TAB, add this line:

TAB: menu-complete

For more details see the READLINE section in man bash.

Thanks to @sth I found what works best for me:

To keep normal bash tab completion, and then use ctl-f to cycle through when needed using menu-complete

put this in your .inputrc file:

"\C-f": menu-complete

On top of

# cycle forward
Control-k: menu-complete
# cycle backward
Control-j: menu-complete-backward

you may also consider adding

# display one column with matches
set completion-display-width 1

This way you would preserve the current Tab functionality and make bash display the possibilities in one column. So instead of

file_12340983421 file_12390983421 file_12390986421 file_12391983421

you would get

file_12340983421
file_12390983421
file_12390986421
file_12391983421

P.S. You can get up to date readline library from this The GNU Readline Library website.

In my experience, the solution provided in sth's answer has never completely worked for me. TL;DR: Add set -o vi to your ~/.bashrc.

When using menu-complete in conjunction with vi keybindings, I have to make sure that my ~/.bashrc has:

set -o vi

It's never been enough for my ~/.inputrc just to have:

TAB: menu-complete


set editing-mode vi
set keymap vi

My guess is that somehow set editing-mode and set keymap are clobbering the TAB: ... setting, but I haven't looked into the documentation thoroughly to figure out why this is the case.

For bash >= 4 you might like these settings. You can try them directly on the command-line, and put them in your ~/.bash_profile if you like them.

# If there are multiple matches for completion, Tab should cycle through them
bind 'TAB:menu-complete'


# Display a list of the matching files
bind "set show-all-if-ambiguous on"


# Perform partial (common) completion on the first Tab press, only start
# cycling full results on the second Tab press (from bash version 5)
bind "set menu-complete-display-prefix on"

This setup is similar to Vim's set wildmode=longest:full:list,full

I pulled these settings from this question on the Unix & Linux site.


By the way, since you are here, here are some other great bindings:

# Cycle through history based on characters already typed on the line
bind '"\e[A":history-search-backward'
bind '"\e[B":history-search-forward'


# Keep Ctrl-Left and Ctrl-Right working when the above are used
bind '"\e[1;5C":forward-word'
bind '"\e[1;5D":backward-word'

This means if you type ssh<Up> it will cycle through previous lines where you ran ssh

If you don't like what you got, you can clear the line with Ctrl-K Ctrl-U

I pulled these settings from this question on AskUbuntu.