Using vim to force edit a file when you opened without permissions

I use vim to edit a file. Sometimes, I forget to have the appropriate permissions. I run vim and the file as a read only file. I can make changes, but I can't actually write the changes. Every once in a while, I end up opening a file and making changes to it, realize that I didn't run it in sudo, scream to myself , and then force quit and open it up again as root user.

Is there a workaround for this? Can I force the changes to the file despite the read only status of the file? Can I at least save the changes, run a diff, and merge the files together?


Solution 1:

There seems to be some different approachs, depending on your current problem:

  1. Readonly by vi. If your file has :set readonly you can
    • Use :w! to force write, or
    • Issue :set noreadonly and then just use normal :w
  2. A permission problem (sudo): you can't write but you have sudo rights.
    • Issue: :w !sudo tee %. This will write the buffer to tee, a command that receives pipe information and can write to files. And as tee is run with sudo powers, tee can modify the file.
  3. A permission problem (no sudo): you don't have rights to write the file and you don't have admin access.
    • Use :w! ~/tempfile.ext to write your changes to a temporary file and then take measures to move the temp file to the directory (send the temp file to the directory owner/admin).

You can read more about it here:

  1. From StackOverflow
  2. From Geekyboy
  3. From Data Agaric

Shortcut

As it is often the case problem #2 (permission problem, with sudo), you can to your /etc/vim/vimrc (or ~/.vimrc) the following shortcut:

  • cnoremap w!! execute 'silent! write !sudo tee % >/dev/null' <bar> edit!

Then you can just type :w!! to save with sudo powers. I won't explain it here but the references above cover many shortcuts.

Solution 2:

I can think of two ways to do this.

The first way assumes you own the file, but the file is READONLY.

Just use vi's exclamation mark suffix to the write command (:w!) to force overwriting your own READONLY file. This of course assumes that you have permission to write and execute in the current folder.

:w!

will cause vi to overwrite the original READONLY file.

The second way assumes someone else owns the file, and you would like to save your changes to that file.

One way to accomplish this is to save the changes made to the original file as an ed script from within vi. This ed script may be applied to the original file (or other similar files) at a later time outside of vi with the ed line editor.

A way to save the current edit session as an ed script is to pass the original file name and the edited vi buffer as standard input to the diff utility with the --ed command line switch i.e. display differences as an ed script.

So, assuming an edited vi buffer, then perform the following

:.,$!diff --ed [original_file] -

This replaces all lines in the current buffer (.,$!) with the diff generated ed script (diff --ed [original_file] -) necessary to convert the original file into the contents of the current buffer. We then want to save this ed script away to a safe place, and apply the script to a version of the original file we can write to. So, save the script away to a writable location, for instance, your login folder:

:w ~/my_ed_script

Now exit vi, and use this ed script to obtain the the edited file that couldn't be saved in the first place. Here is how to accomplish that from the bash command line prompt, '$':

$ (cat ~/my_ed_script && echo 'w') | ed - writable_copy_of_original_file

What this command sequence does in words is to catenate the script we generated with diff and echoes the ed write command, 'w', to the standard input of ed. Ed then applies this script to the writable copy of the original file, and writes those modified buffer changes back out to the file.

So that is a way to save work performed in vi to a file which had originally been owned by someone else using vi, diff, and ed.