How does `:w !sudo tee %` work
Solution 1
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.
Solution 2
%
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
Solution 3
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.
Related videos on Youtube
Ali
I love to build things that people love to use. I like scientific data analysis. I've spent most of my life in medicine and neuroscience! I like: vim, zsh, golang, debian, python I am addicted to writing code! and learning new things!!
Updated on September 18, 2022Comments
-
Ali over 1 year
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 thesudo tee
command and%
represents the current buffer content right?
But still don't understand how this works. -
Satō Katsura over 7 years
:!command
is a filter (cf.:h !
), while:w !command
is not, it just executescommand
with the current file asstdin
(cf.:h :w_c
). To wit::w !sed /./d
doesn'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. -
user3426706 over 4 yearsAnd what is
tee
? -
jalanb almost 3 years
tee
is a Linux command used to split streams, like a "T-splitter" in plumbing. More info at Wikipedia: en.wikipedia.org/wiki/Tee_(command)