Vim Tips Wiki
No edit summary
 
Tag: Source edit
 
(11 intermediate revisions by 6 users not shown)
Line 1: Line 1:
  +
{{TipImported
{{review}}
 
{{Tip
 
 
|id=975
 
|id=975
  +
|previous=974
|title=su-write
 
  +
|next=976
|created=August 18, 2005 17:03
+
|created=2005
 
|complexity=basic
 
|complexity=basic
 
|author=Bernard Pratz
 
|author=Bernard Pratz
 
|version=6.0
 
|version=6.0
 
|rating=7/3
 
|rating=7/3
  +
|category1=
|text=
 
  +
|category2=
I just wrote a little function that uses sudo and cp to save a file whose modes wouldn't allow me to write it.
 
 
Obviously, it preserves the modes of the original file, though it is being rewrited. Of course, this tip has to
 
 
be used with real caution, as it gets you more power...
 
 
 
 
TODO:
 
 
The only real drawback is there's no check for symlinks, and then, the symlink would get removed and
 
 
replaced by a file with the symlink's modes, which are 777...
 
 
Another thing that would be nice, would be to integrate it to the interface, to get it work when :w is not
 
 
enough, or at least having an alias like :wforce, :w!! or :whatever...
 
 
 
 
function Suedit() {
 
 
let fname=tempname()
 
 
exe 'w '.fname
 
 
let modes=system('find . -maxdepth 1 -name '.expand("%").' -printf "%m"')
 
 
exec '!sudo cp '.fname.' '.expand("%")
 
 
exec '!sudo chmod '.modes." ".expand("%")
 
 
}
 
 
 
 
}}
 
}}
  +
Sometimes you modify a file, for example from the <code>/etc</code> directory, then when you try to save the file, you get a permission-denied error. This tip presents some suggestions for using sudo from with Vim, so you can successfullly write the file with temporary privileges.
   
 
Of course, this tip has to be used with caution, as it gets you more power.
== Comments ==
 
just use :
 
system('stat -c%a '.expand("%"))
 
instead of
 
system('find . -maxdepth 1 -name '.expand("%").' -printf "%m"')
 
   
  +
==Suggestion 1==
useless use of find O:-)
 
  +
If you find you do not have permission to perform <code>:w</code>, use the following:
thanks to strull for the clever suggestion
 
  +
<pre>
 
:w !sudo tee "%" > /dev/null
  +
</pre>
   
  +
You can make a command so <code>:W</code> invokes sudo:
--
 
  +
<pre>
Guyzmo
 
 
command W w !sudo tee "%" > /dev/null
  +
</pre>
   
  +
Or, if you know about the problem beforehand:
bernardATpratzDOTnet
 
  +
<pre>
, August 18, 2005 17:20
 
  +
sudoedit path_to_file
----
 
  +
sudo -e path_to_file
I just forgot a detail, to restore the user/group of the original file :
 
  +
</pre>
 
function Suedit()
 
let fname=tempname()
 
exe 'w '.fname
 
let owner=system('stat -c%U:%G '.expand("%"))
 
let modes=system('stat -c%a '.expand("%"))
 
exec '!sudo cp '.fname.' '.expand("%")
 
exec '!sudo chmod '.modes." ".expand("%")
 
exec '!sudo chown '.owner'" ".expand("%")
 
endfunction
 
 
this time, I hope it'll work correctly
 
 
--
 
Guyzmo
 
(going to bed)
 
 
bernardATpratzDOTnet
 
, August 18, 2005 17:26
 
----
 
I have made no tests on this script, that should work as is... When I'll have time, I'll make a script around
 
that to check for all errors, with confirmation and all that stuff, and be free to do it before me, if you got the
 
time to do so :P
 
 
--
 
Guyzmo
 
 
bernardATpratzDOTnet
 
, August 18, 2005 17:36
 
----
 
Spare yourself the effort: [/scripts/script.php?script_id=729 vimscript &#35;729] already does this.
 
 
pagaltzis--AT--gmx.de
 
, August 18, 2005 20:46
 
----
 
Except when the system lacks sudo. (forex: vanilla FreeBSD and OpenBSD installs)
 
 
 
foltiATbalabitDOThu
 
, August 19, 2005 3:58
 
----
 
What's your point? Of course you can't use permissions granted via sudo if you don't have sudo.
 
 
pagaltzis--AT--gmx.de
 
, August 19, 2005 5:40
 
----
 
Why is sudo dragged into vim, use the shell.
 
 
Jake
 
, August 19, 2005 15:15
 
----
 
For the same reason that wget or scp or rsync have been dragged into Vim?
 
 
pagaltzis--AT--gmx.de
 
, August 20, 2005 3:47
 
----
 
:w !sudo tee %
 
 
It's very simple.
 
 
gorou
 
, August 23, 2005 22:40
 
----
 
&gt; :w !sudo tee %
 
&gt; It's very simple.
 
 
... and quite clever! ;-)
 
 
Minor improvement to prevent tee's stdout from "cluttering" your vim session:
 
 
:w !sudo tee % &gt; /dev/null
 
 
But Jake makes a good point, though: why not just:
 
 
sudo vi &lt;file_whose_modes_wouldn't_allow_me_to_write_it&gt;
 
 
Or, if you don't want to run your entire vim sesion as sudo:
 
 
[/scripts/script.php?script_id=729 vimscript &#35;729] : sudo.vim
 
 
Peter Vandenberk
 
 
 
pvdbp--AT--yahoo.co.uk
 
, August 24, 2005 3:51
 
----
 
:w !sudo tee % &gt; /dev/null
 
   
  +
==Suggestion 2==
Is BRILLIANT!
 
  +
The following function saves the current file to a temporary file, then copies the new file to replace the original. It preserves the modes of the original file, though it is being rewritten.
  +
<pre>
 
function Suedit()
 
let fname=tempname()
  +
exec 'w' fname
  +
let writetarget=shellescape(expand("%:p"))
 
let owner=shellescape(system('stat --printf=%U:%G ' . writetarget))
 
let modes=system('stat --printf=c%a ' . writetarget)
  +
exec '!sudo cp' shellescape(fname) writetarget
  +
exec '!sudo chmod' modes writetarget
 
exec '!sudo chown' owner writetarget
 
endfunction
  +
</pre>
   
 
'''Warning''' There is no check for symlinks. A symlink would be removed and replaced by a file with the symlink's modes, which are 777.
[quote]
 
But Jake makes a good point, though: why not just:
 
   
  +
==Suggestion 3==
sudo vi &lt;file_whose_modes_wouldn't_allow_me_to_write_it&gt;
 
  +
Here is a mapping to save to a <code>/tmp</code> file, then overwrite the working file.
  +
<pre>
  +
nnoremap <leader>es :w! /tmp/sudoSave \| let $fileToSave=expand('%') \| let $fileToSaveBackup=expand('%').'~' \| !sudo cp $fileToSave $fileToSaveBackup && sudo cp /tmp/sudoSave $fileToSave<CR><ESC>:e!<CR>
  +
</pre>
   
  +
'''Warning''' This command will reload the file; you will lose the modifications history (undo will not work, although it does keep a backup).
Peter Vandenberk
 
[/quote]
 
   
  +
Note that a backup is made, even when '<code>nobackup</code>' is set.
Peter,
 
I often forget to open a file as sudo, or open a file expecting to only view it, and then find a problem with it. This saves me from having to:
 
:w /tmp/%
 
Then sudo mv the file in place after I exit. I love it!
 
   
 
==Comments==
I also try to learn to do things without plugin and custom mappings so that I can use it on any system. I use hundreds of servers and rarely have access to my .vimrc
 
  +
Use {{script|id=729}} which has had more testing or use {{script|id=2709}} which is an improved version of the first plugin (since it is not developed any more).
   
RichardBronosky (first--AT--last.com)
 
, July 12, 2006 8:02
 
 
----
 
----
<!-- parsed by vimtips.py in 0.686125 seconds-->
 

Latest revision as of 03:43, 22 May 2021

Tip 975 Printable Monobook Previous Next

created 2005 · complexity basic · author Bernard Pratz · version 6.0


Sometimes you modify a file, for example from the /etc directory, then when you try to save the file, you get a permission-denied error. This tip presents some suggestions for using sudo from with Vim, so you can successfullly write the file with temporary privileges.

Of course, this tip has to be used with caution, as it gets you more power.

Suggestion 1[]

If you find you do not have permission to perform :w, use the following:

:w !sudo tee "%" > /dev/null

You can make a command so :W invokes sudo:

command W w !sudo tee "%" > /dev/null

Or, if you know about the problem beforehand:

sudoedit path_to_file
sudo -e path_to_file

Suggestion 2[]

The following function saves the current file to a temporary file, then copies the new file to replace the original. It preserves the modes of the original file, though it is being rewritten.

function Suedit()
  let fname=tempname()
  exec 'w' fname
  let writetarget=shellescape(expand("%:p"))
  let owner=shellescape(system('stat --printf=%U:%G ' . writetarget))
  let modes=system('stat --printf=c%a ' . writetarget)
  exec '!sudo cp' shellescape(fname) writetarget
  exec '!sudo chmod' modes writetarget
  exec '!sudo chown' owner writetarget
endfunction

Warning There is no check for symlinks. A symlink would be removed and replaced by a file with the symlink's modes, which are 777.

Suggestion 3[]

Here is a mapping to save to a /tmp file, then overwrite the working file.

nnoremap <leader>es :w! /tmp/sudoSave \| let $fileToSave=expand('%') \| let $fileToSaveBackup=expand('%').'~' \| !sudo cp $fileToSave $fileToSaveBackup && sudo cp /tmp/sudoSave $fileToSave<CR><ESC>:e!<CR>

Warning This command will reload the file; you will lose the modifications history (undo will not work, although it does keep a backup).

Note that a backup is made, even when 'nobackup' is set.

Comments[]

Use script#729 which has had more testing or use script#2709 which is an improved version of the first plugin (since it is not developed any more).