8

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?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.