If you open a file that you don't have permission to write to in vim, then decide you need to change it, you can write your changes without exiting vim by doing :w !sudo tee %
I don't understand how this can work. Can you please dissect this?
I understand the :w part, it writes the current buffer to disk, assuming there already is a file name associated with it, right?
I also understand the ! which executes the sudo tee command and % represents the current buffer content right?
But still don't understand how this works.
3 Answers
The structure :w !cmd means "write the current buffer piped through command". So you can do, for example :w !cat and it will pipe the buffer through cat.
Now % is the filename associated with the buffer
So :w !sudo tee % will pipe the contents of the buffer through sudo tee FILENAME. This effectively writes the contents of the buffer out to the file.
- And what is
tee?CodyBugstein– CodyBugstein2019-12-05 18:07:21 +00:00Commented Dec 5, 2019 at 18:07 -
teeis a Linux command used to split streams, like a "T-splitter" in plumbing. More info at Wikipedia: en.wikipedia.org/wiki/Tee_(command)jalanb– jalanb2021-05-27 13:50:21 +00:00Commented May 27, 2021 at 13:50
% represents the current buffer's filename, not its contents.
so :w !sudo tee % means pipe the current buffer to sudo tee [currentfilename].
tee is being run as root, so has write access to save its stdin to the file.
See also https://stackoverflow.com/questions/2600783/how-does-the-vim-write-with-sudo-trick-work
Not quite right!
!command runs command as a filter command, which get text from stdin, do something and output to stdout.
By using w, you pushed file content to stdin of sudo tee %. % is special register in vim, which holds the name of current file.
So you got sudo tee FILENAME, which will push tee stdin - file content - to current file.
- 2
:!commandis a filter (cf.:h !), while:w !commandis not, it just executescommandwith the current file asstdin(cf.:h :w_c). To wit::w !sed /./ddoesn't change the content of the current buffer. But the recipe is indeed not quite right for another reason,%needs to be escaped::exec 'w !sudo tee ' . shellescape(expand('%', 1)). The original command doesn't work with, say, filenames with spaces.Satō Katsura– Satō Katsura2016-08-04 12:11:46 +00:00Commented Aug 4, 2016 at 12:11