How to save files with root permissions in VIM started by a common user

Source: Internet
Author: User

A friend who works on Linux may have encountered such a situation. When you use Vim to edit a file, run:wqSave and exit. An error occurs:

E45: ‘readonly‘ option is set (add ! to override)

This indicates that the file is read-only. Follow the prompts and add!Force save::w!, Another error occurs:

"readonly-file-name" E212: Can‘t open file for writing

Why cannot I open the file because it exists clearly? What does this error mean? View document:help E212:

For some reason the file you are writing to cannot be created or overwritten.The reason could be that you do not have permission to write in the directoryor the file name is not valid.

It may have no permissions. This reminds you that this file requires the root permission to be edited. Currently, only common users are logged in. You forgot to use this file before editing.sudoTo start vim. To prevent the loss of the modification, you have to save it as another temporary file first.temp-file-nameAnd then exit vim and runsudo mv temp-file-name readonly-file-nameOverwrite the original file.

Directory
  • Solution
    • Execute External commands in VIM
    • Another representation of the command
    • % Meaning
    • Role of TEE
    • After the command is executed
  • Simpler solution: ing
  • Another idea
    • Redirection Problems
    • Redirection Scheme
  • Written at the end

However, this operation is too cumbersome. What should I do if I want to save the file and modify it later, I want to keep the vim working state, such as editing history and buffer status? Can I get the root permission to save the file without exiting Vim?

Solution

The answer is yes. Run the following command:

:w !sudo tee %

Next we will analyze why this command can work. First view the document:help :wScroll down to see:

*:w_c* *:write_c*
:[range]w[rite] [++opt] !{cmd}
			Execute {cmd} with [range] lines as standard input
			(note the space in front of the ‘!‘).  {cmd} is
			executed like with ":!{cmd}", any ‘!‘ is replaced with
			the previous command |:!|.

The default [range] for the ":w" command is the whole buffer (1,$)

The following command maps the usage method to the preceding command:

:       w               !sudo tee %
|       |               |  |
:[range]w[rite] [++opt] !{cmd}

We did not specifyrange, See the bottom line of the help document, whenrangeIf not specified, the entire file is used by default. In addition, it is not specified hereopt.

Execute External commands in VIM

Next is an exclamation point!It indicates that the following part is an external command, that issudo tee %. The document clearly states that this and direct execution:!{cmd}Is the same effect. The latter is used to open shell to execute a command, for example, run:!lsIt will display all files in the current working directory. This is very useful. Any command that can be executed in shell can be run without exiting vim, you can also read the results into vim. Imagine if you want to insert all the file names in the current working path or current working path in Vim, you can run:

: R! PWD or: R! Ls

At this time, all the content will be read into Vim without exiting Vim. Execute the command and copy and paste it to vim. With it, VIM can operate the shell freely without exiting.

Another representation of the command

See the previous document:

Execute {cmd} with [range] lines as standard input

So in fact:wThe current file is not really saved, just like executing:w new-file-nameIt saves the content of the current file to anothernew-file-nameIn the file, it is equivalent toSaveInsteadSave. It writes the content of the current document to the endcmdAnd then executecmdTherefore, the entire command can be converted to a common shell command with the same functions:

$ cat readonly-file-name | sudo tee %

It looks "normal. WheresudoIt is easy to understand, meaning to switch to the root to execute the following command,teeAnd%What is it?

% Meaning

Let's take a look.%, Execute:help cmdline-specialYou can see:

In Ex commands, at places where a file name can be used, the following
characters have a special meaning.  These can also be used in the expression
function expand() |expand()|.
	%	Is replaced with the current file name.		  *:_%* *c_%*

When executing an external command,%Will be extended to the current file name, so the abovecmdThat issudo tee readonly-file-name. In this case, the entire command is:

$ cat readonly-file-name | sudo tee readonly-file-name

Note:: We often use it in another place.%Yes, replace. But there%Different roles, execute:help :%View the document:

Line numbers may be specified with:		*:range* *E14* *{address}*
	{number}	an absolute line number
	...
	%		equal to 1,$ (the entire file)		  *:%*

In replacement,%It indicates the entire file, not the file name. Therefore, for commands:%s/old/new/gIt indicates replacing the old in the entire document with new instead of replacing the old in the file name with new.

Role of TEE

There is only one difficulty: Tee. What exactly does it use? Wikipedia provides a detailed explanation. You can also view man page. The following figure shows the image.teeHow it works:


ls -lThe output is passed through the pipelineteeThe latter has done two things: first copy a copy of data to the filefile.txtAt the same time, copy a copy to its standard output. The data is sent to the MPs queue again.lessSo it copies and saves the data to the file without affecting the original pipeline. Look at the middle part. It looks like a capital letter.TAdds a branch to the data flow,tee.

Now the above commands are easy to understand,teeWrite the content in the standard inputreadonly-file-nameTo update the read-only file. Of course, there is actually another half of the data:teeBut because there are no other commands, this output is equivalent to being discarded. Of course, you can also add it later.> /dev/nullTo explicitly discard the standard output, but this does not affect the entire operation and will increase the number of characters entered. Therefore, you only need the preceding command.

After the command is executed

After running the preceding command, the following prompt appears:

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

Vim prompts for file update and asks whether to confirm or reload the file. Directly inputOIn this way, the running status of VIM can be retained, such as the editing history, buffer, and other operations. If you selectL, The file will be opened with a new file, and all the working states will be lost. At this time, undo cannot be performed, and the content in the buffer will be cleared.

Simpler solution: ing

The above method perfectly solves the problem raised at the beginning of the article, but after all, the command is still somewhat long. To avoid entering a long string of commands every time, you can map it into a simple command and add it.vimrcMedium:

1  " Allow saving of files as sudo when I forgot to start vim using sudo. 2     cmap w!! w !sudo tee > /dev/null %

In this way, simple operation:w!!You can. Half of the command> /dev/nullAs explained above, the function is to explicitly discard the standard output content.

Another idea

So far, a perfect but tricky solution has been completed. You may ask, why not use the following more common commands? Isn't this easier to understand and simpler?

:w !sudo cat > %
Redirection Problems

Let's analyze it again. As before, it can be converted to shell commands with the same function:

$ cat readonly-file-name | sudo cat > %

This command does not seem to have any problems, but once it is run, another error occurs:

/bin/sh: readonly-file-name: Permission denied

shell returned 1

What's going on? Not clearly addedsudoWhy do I still prompt that I have no permission? The reason is that the redirection is performed by the shell. Before all commands start, the shell will execute the redirection operation, so the redirection is not affected.sudoThe current shell itself is started as a normal user and has no permission to write this file. Therefore, the above error occurs.

Redirection Scheme

Here we introduce several methods to solve the error of no permission for redirection, exceptteeIn addition, there is a more convenient solution:sudoOpen a shell and execute the redirection-containing command in the shell with the root permission, for example:

:w !sudo sh -c ‘cat > %‘

However, because of the existence of single quotes%It will not be expanded. It is passed to the shell intact, and in the shell, a separate%Equivalentnil, So the file is redirectednilFailed to save the file because all content is lost.

Since it is because%If the error is not displayed, try to enclose the single quotes‘Double quotation marks"Try again:

:w !sudo sh -c "cat > %"

Successful! This is because before the command is passed to the shell,%It has been extended to the current file name. For the differences between single quotes and double quotes, refer to here. Simply put, single quotes will pass the internal content intact to the command, but double quotes will show some content, such as variables and escape characters.

Of course, you can map it into a simple command and add it to. vimrc as before:

1  " Allow saving of files as sudo when I forgot to start vim using sudo. 2     cmap w!! w !sudo sh -c "cat > %"

Note: you do not need to redirect the output/dev/null.

Written at the end

Now, with the powerful flexibility of VIM, we have implemented two solutions to save the files that require root permission in VIM started by common users. The two work in a similar way. They both use Vim to execute External commands. The difference is that they use different shell commands.

 

Post, original article address: feihu. Me/blog/2014/vim-Write-read-only-file/

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.