Delete last word (Ctrl-W): Make bash shell behave like vim command line

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?


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 

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>

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?