27

Sometimes it happens that I open a file and make some modifications as my own user, without noticing or "forgetting" to noticing the [read-only] warning in the status line (ie. some random /etc config file like /etc/resolv.conf).

:w! obviously fails in this case because my user has no write permission anyway. So I have to :w /home/filename, exit and sudo mv ..., very uncomfortable.

Is there a way so that I escalate temporarily to root to be able to save the file currently opened? (given I am in sudoers or/and I can su directly)?

2 Answers 2

24

The trick is to use an external call to sudo:

:w !sudo tee %

How this works:

  • :w !<command> executes <command> with the contents of the buffer as stdin.
  • tee duplicates stdin to a file & stdout; % expands to the current filename..
  • You prefix this with sudo for root permissions.

You're not really saving the file with Vim, rather, you're calling an external program to overwrite the contents of the file you're editing. This is why you will get a warning from Vim:

W12: Warning: File "xxx" has changed and the buffer was changed in Vim as well
See ":help W12" for more info.
[O]K, (L)oad File: 

You could turn this into a function:

fun! SuperWrite()
        write !sudo tee %
        " Or with :silent (but that doesn't seem to work for everyone)
        "silent write !sudo tee %
        edit!
endfun

And keybind:

nnoremap <Leader>w! :call SuperWrite()<CR>

With su, only the root user can use -c to immediately execute a command. I don't think you can use su to do this, but perhaps there is a trick I am unaware of...

7
  • SuperWrite works, but it echoes the file back at you. Running it :silently has you enter your password invisibly. Feb 23, 2015 at 23:38
  • @TankorSmash Thanks; updated answer. Not sure what you mean with "enter your password invisibly", though? Adding silent seems to work fine? Feb 23, 2015 at 23:41
  • I don't run vim with sudo, so that may be at play here, but when I go to sudo tee the file, it prompts me for the sudo password. If its silent, I don't see the prompt, but still need to enter a password. Feb 24, 2015 at 4:52
  • 1
    What you're seeing is tee's standard functionality of echoing to stdout as well as the file given. A solution is to redirect stdout to /dev/null, a la: w ! tee % > /dev/null This will still echo the result of the command (a single line), but not the entire buffer contents.
    – Jon Carter
    Feb 24, 2015 at 7:01
  • Rather than using tee then throwing away its output, wouldn't cat also work if you don't want the file printed out?
    – Lie Ryan
    Feb 26, 2015 at 11:08
12

I use the following mapping in my .vimrc, which I find useful:

cnoremap w!! w !sudo tee %

It's easy to remember, because w is "write," w! is "force write," and w!! is "super-duper-force write." :P

1
  • 1
    I've long had it mapped to W, but w!! makes much more sense, shall update my .vimrc. Thanks
    – jalanb
    Feb 6, 2015 at 0:17

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.