I've been meaning to find a solution for this for YEARS.
I am sooo much more productive in vim when manipulating files than bash for this reason.
If I have
file_12390983421
file_12391983421
file_12340983421
file_12390986421
In bash and type file_1->tab , it obviously lists:
file_12390983421 file_12391983421 file_12340983421 file_12390986421
And this is a horrible bore and painful to work with.
The same sequence in vim will loop through the files one at a time.
Please someone tell me how to do this in bash, or if there is another shell that can do this, I'll switch tomorrow.
bind TAB:menu-complete
in .bashrc
.
vi
editing mode (set -o vi
)
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
.
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 is another nice pair of bindings:
# Cycle through history based on characters already typed on the line
bind '"\e[A":history-search-backward'
bind '"\e[B":history-search-forward'
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.
bash --version
. My Mac has only bash version 3, which unfortunately means the last two binds will have no effect.
bash
(currently 5.0.2) on macOS at stackoverflow.com/a/55011144/117471
.inputrc
is where they are "supposed" to go (and may reduce parsing by bash). But on investigation, I see that bindings put into .inputrc
will be used not only by bash, but by all programs which use readline!
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.
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
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.
set...
part goes in ~/.bashrc
, the second TAB:...
part goes in ~/.inputrc
. You'd get TAB command not found
if you put that part in ~/.bashrc
.
Success story sharing
menu-complete-backward
, and at least on my terminal Shift-Tab seems to send the\e[Z
escape sequence. This gives you this .inputrc entry:"\e[Z": menu-complete-backward
Tab:complete "\e[Z":menu-complete
in my.inputrc
. That way,Tab
has the original behavior andShift
+Tab
lets you cycle through suggestions. Edit: There's supposed to be a line break afterTab:complete
. I can't properly style that here in the comments.