9

Among the many useful keyboard shortcuts available in the bash shell, there is Ctrl-W to delete the word to the left of the cursor. Let's suppose my command line looks like the following:

cp some-file /foo/bar/baz/copy

Now I'd expect to be able to press Ctrl-W and end up with the following:

cp some-file /foo/bar/baz/

In Vim's command line it actually works this way: Only alphanumeric characters are treated as "word", whereas special characters (like /) serve as delimiters marking the start of a new "word".

But unfortunately it doesn't work like that in all shells I've used so far. Only spaces will delimit a "word", so pressing the shortcut with the command line shown above will give me:

cp some-file

Is there a way to make Bash behave like Vim? Some configuration I can put into my .bashrc?

1
  • 1
    See this question and pay attention to this answer. For some reason it is not upvoted, but it does exactly what you want.
    – taketwo
    Jan 23, 2014 at 11:29

3 Answers 3

12

This has nothing to do with Vim, all editors behave that way (including emacs), they treat non-word characters as delimiters. Anyway, the behavior you are talking about is controlled by readline and its manual lists quite a few commands you can assign shortcuts to. I am pasting a few relevant ones here but I recommend you read man readline for more info:

   backward-word (M-b)
          Move  back  to  the  start  of the current or previous word.  Words 
          are composed of alphanumeric characters (letters and digits).

   kill-line (C-k)
          Kill the text from point to the end of the line.
   kill-word (M-d)
          Kill from point the end of  the  current  word,  or  if  between
          words,  to  the  end  of the next word.  Word boundaries are the
          same as those used by forward-word.
   backward-kill-word (M-Rubout)
          Kill the word behind point.  Word boundaries  are  the  same  as
          those used by backward-word.
   unix-word-rubout (C-w)
          Kill  the  word behind point, using white space as a word bound‐
          ary.  The killed text is saved on the kill-ring.
   unix-filename-rubout
          Kill the word behind point, using  white  space  and  the  slash
          character  as  the word boundaries.  The killed text is saved on
          the kill-ring.

So, the one you want is backward-kill-word, which uses non alphanumeric characters as word boundaries. By default, it is assigned to Alt+Backspace but you can change that by using either the global /etc/inputrc if you want them to apply to all users or (better) your own local $HOME/.inputrc.

As far as I can tell, Ctrl+W seems to be reserved and you can't use that one but you can choose another shortcut, Ctrl+J for example. Create a $HOME/.inputrc file if it doesn't exist and add this line to it:

Control-J: backward-kill-word 

That should be enough for most modern terminal emulators. However, some older terminals use different codes. If you're using xterm, for example, the line above should be written as:

C-J: backward-kill-word 
4
  • Very thorough explanation, thanks! In the end, I chose to use this approach. Jan 23, 2014 at 19:50
  • 5
    \C-w is not reserved. Just run bind 'set bind-tty-special-chars off' to turn off the bind-tty-special-chars setting that causes readline to re-read and re-bind the terminal's special characters (in this case the werase character) every time that a new line is to be input.
    – JdeBP
    Jan 23, 2014 at 19:57
  • @JdeBP ah, OK, thanks. I just saw that it was explicitly mentioned in the man page and that I could not overwrite the setting in my .inputrc.
    – terdon
    Jan 23, 2014 at 20:06
  • Please note that: backward-kill-word does not work like in vim... foo/bar will be deleted in 3 ctrl+w, ie foo/bar -> foo/ -> foo -> deleted, where in the shell, foo/bar -> foo/ -> deleted
    – azorius
    Sep 6, 2017 at 12:56
5

You can enable readline's (and thus bash's) so called "vi mode" by putting the following lines in ~/.inputrc and starting a new shell:

set editing-mode vi
set keymap vi-command

But you will notice that <C-w> works the same as with the default Emacs mode: words are space-delimited. You can do dT/ or similar commands, though. It's still an emulation, not the real deal. The available mappings are listed in readline's manual:

$ man readline
/VI

See also this page on the Vim wiki.

But I don't think readline's vi mode is that useful, if you often find yourself in need of seriously editing your command line… why not use Vim for real?

<C-x><C-e>
1
  • Wow that last shortcut to invoke my editor is great! Although if my command line reaches that level of complexity, I'll rather stick it in a shell script. Still, good to know! Jan 23, 2014 at 19:49
1

There are two options that I know of, though neither directly does what you ask.

  1. set bash to use vi mode, where the prompt then behaves like a line in vi. The command is set -o vi. Ref: BASH Help - A Bash Tutorial
  2. Add vi key maps to your current shell prompt. Ref: StackOverflow: What does set key map vi do?

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .