请选择 进入手机版 | 继续访问电脑版

[LINUX] Linux环境下VI/VIM编辑文件时无权限保存的办理 方法(平凡 用户)

[复制链接]
查看36 | 回复5 | 2021-9-5 07:14:14 | 显示全部楼层 |阅读模式

在Linux环境下,假如 直接利用 VI/VIM下令 编辑没有修改权限的文件时,保存的时间 就会提示用户无法举行 保存操作,一样平常 的办理 方法只能是关闭文件重新以sudo权限打开该文件编辑后再保存(条件 是用户具有sudo权限)。实在 ,在VI/VIM模式下通过一些简单的下令 ,就能在不关闭当前文件的环境 下达到保存文件的目的 。

方法一

关于%! sudo tee % > /dev/null这条下令 的阐明 如下

此下令 是把当前文件(即%)作为stdin传给sudo tee下令 来实行 。

方法二
 

在Linux上工作的朋侪 很大概 遇到 过如许 一种环境 ,当你用Vim编辑完一个文件时,运行:wq保存退出,忽然 蹦出一个错误:

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

这表明文件是只读的,按照提示,加上!逼迫 保存::w!,效果 又一个错误出现:

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

文件明显 存在,为何提示无法打开?这错误又代表什么呢?查看文档: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 directory
or the file name is not valid.

原来是大概 没有权限造成的。此时你才想起,这个文件必要 root权限才能编辑,而当前登陆的只是平常 用户,在编辑之前你忘了利用 sudo来启动Vim,以是 才保存失败。于是为了防止修改丢失,你只好先把它保存为别的 一个暂时 文件temp-file-name,然后退出Vim,再运行sudo mv temp-file-name readonly-file-name覆盖原文件。

但如许 操作过于繁琐。而且假如 只是想暂存此文件,还必要 接着修改,则渴望 保留Vim的工作状态,比如编辑汗青 ,buffer状态等等,该怎么办?能不能在不退出Vim的环境 下获得root权限来保存这个文件?

办理 方案

答案是可以,实行 如许 一条下令 即可:

  1. :w !sudo tee %
复制代码

接下来我们来分析这个下令 为什么可以工作。起首 查看文档:help :w,向下滚动一点可以看到:

  1. *:w_c* *:write_c*
  2. :[range]w[rite] [++opt] !{cmd}
  3. Execute {cmd} with [range] lines as standard input
  4. (note the space in front of the '!'). {cmd} is
  5. executed like with ":!{cmd}", any '!' is replaced with
  6. the previous command |:!|.
  7. The default [range] for the ":w" command is the whole buffer (1,$)
复制代码

把这个利用 方法对应前面的下令 ,如下所示:

  1. : w !sudo tee %
  2. | | | |
  3. :[range]w[rite] [++opt] !{cmd}
复制代码

我们并未指定

  1. range
复制代码
,参见帮助文档最下面一行,当
  1. range
复制代码
未指定时,默认环境 下是整个文件。此外,这里也没有指定opt。

Vim中实行 外部下令

接下来是一个叹号!,它表示厥后 面部分是外部下令 ,即

  1. sudo tee %
复制代码
。文档中说的很清晰 ,这和直接实行
  1. :!{cmd}
复制代码
是一样的效果 。后者的作用是打开shell实行 一个下令 ,比如,运行
  1. :!ls
复制代码
,会表现 当前工作目次 下的全部 文件,这非常有用 ,任何可以在shell中实行 的下令 都可以在不退出Vim的环境 下运行,并且可以将效果 读入到Vim中来。试想,假如 你要在Vim中插入当前工作路径或者当前工作路径下的全部 文件名,你可以运行:

  1. :r !pwd或:r !ls
复制代码

此时全部 的内容便被读入至Vim,而不必要 退出Vim,实行 下令 ,然后拷贝粘贴至Vim中。有了它,Vim可以自由的操作shell而无需退出。

下令 的另一种表示情势

再看前面的文档:

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

以是 现实 上这个:w并未真的保存当前文件,就像实行 :w new-file-name时,它将当前文件的内容保存到别的 一个new-file-name的文件中,在这里它相称 于一个另存为,而不是保存。它将当前文档的内容写到后面cmd的标准输入中,再来实行 cmd,以是 整个下令 可以转换为一个具有雷同 功能的平常 shell下令 :

  1. $ cat readonly-file-name | sudo tee %
复制代码

如许 看起来”正常”些了。此中 sudo很好明白 ,意为切换至root实行 后面的下令 ,tee和%是什么呢?

%的意义

我们先来看%,实行

  1. :help cmdline-special
复制代码
可以看到:

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

在实行 外部下令 时,%会扩展成当前文件名,以是 上述的

  1. cmd
复制代码
也就成了
  1. sudo tee readonly-file-name
复制代码
。此时整个下令 即:

  1. $ cat readonly-file-name | sudo tee readonly-file-name
复制代码

注意 :在别的 一个地方我们也常常 用到%,没错,更换 。但是那里 %的作用不一样,实行 :help :%查看文档:

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

在更换 中,%的意义是代表整个文件,而不是文件名。以是 对于下令 :%s/old/new/g,它表示的是更换 整篇文档中的old为new,而不是把文件名中的old换成new。

tee的作用

如今 只剩一个难点: tee。它毕竟 有何用?维基百科上对其有一个具体 的表明 ,你也可以查看

  1. man page
复制代码
。下面这幅图很形象的展示了tee是怎样 工作的:

Linux环境下VI/VIM编辑文件时无权限保存的办理
方法(平凡
用户)

  1. ls -l
复制代码
的输出颠末 管道传给了tee,后者做了两件事,起首 拷贝一份数据到文件file.txt,同时再拷贝一份到其标准输出。数据再次颠末 管道传给less的标准输入,以是 它在不影响原有管道的基础上对数据作了一份拷贝并保存到文件中。看上图中央 部分,它很像大写的字母T,给数据活动 增长 了一个分支,tee的名字也由此而来。

如今 上面的下令 就轻易 明白 了,tee将其标准输入中的内容写到了

  1. readonly-file-name
复制代码
中,从而达到了更新只读文件的目的 。当然这里实在 还有别的 一半数据:
  1. tee
复制代码
的标准输出,但由于 后面没有跟别的 的下令 ,以是 这份输出相称 于被扬弃 。当然也可以在后面补上>
  1. /dev/null
复制代码
,以显式的丢弃标准输出,但是这对整个操作没有影响,而且会增长 输入的字符数,因此只需上述下令 即可。

下令 实行 之后

运行完上述下令 后,会出现下面的提示:

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

Vim提示文件更新,扣问 是确认还是重新加载文件。建议直接输入O,由于 如许 可以保留Vim的工作状态,比如编辑汗青 ,buffer等,撤消等操作仍旧 可以继续。而假如 选择L,文件会以全新的文件打开,全部 的工作状态便丢失了,此时无法实行 撤消,buffer中的内容也被清空。

更简单的方案:映射

上述方式非常美满 的办理 了文章开始提出的标题 ,但毕竟下令 还是有些长,为了避免每次输入一长串的下令 ,可以将它映射为一个简单的下令 加到.vimrc中:

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

如许 ,简单的运行:w!!即可。下令 后半部分> /dev/null在前面已经表明 过,作用为显式的丢掉标准输出的内容。

另一种思绪

至此,一个比较美满 但很tricky的方案已经完成。你大概 会问,为什么不用下面如许 更常见的下令 呢?这不是更轻易 明白 ,更简单一些么?

  1. :w !sudo cat > %
复制代码

重定向的标题

我们来分析一遍,像前面一样,它可以被转换为雷同 功能的shell下令 :

  1. $ cat readonly-file-name | sudo cat > %
复制代码

这条下令 看起来一点标题 没有,可一旦运行,又会出现别的 一个错误:

  1. /bin/sh: readonly-file-name: Permission denied
  2. shell returned 1
复制代码

这是怎么回事?不是明显 加了sudo么,为什么还提示说没有权限?稍安勿躁,缘故原由 在于重定向,它是由shell实行 的,在统统 下令 开始之前,shell便会实行 重定向操作,以是 重定向并未受sudo影响,而当前的shell本身也是以平常 用户身份启动,也没有权限写此文件,因此便有了上面的错误。

重定向方案

这里先容 了几种办理 重定向无权限错误的方法,当然除了

  1. tee
复制代码
方案以外,还有一种比较方便的方案:以
  1. sudo
复制代码
打开一个
  1. shell
复制代码
,然后在该具有root权限的shell中实行 含重定向的下令 ,如:

  1. :w !sudo sh -c 'cat > %'
复制代码

但是 如许 实行 时,由于单引号的存在,以是 在Vim中%并不会睁开 ,它被原封不动的传给了shell,而在shell中,一个单独的%相称 于nil,以是 文件被重定向到了nil,全部 内容丢失,保存文件失败。

既然是由于%没有展开导 致的错误,那么试着将单引号'换成双引号"再试一次:

  1. :w !sudo sh -c "cat > %"
复制代码

成功!这是由于 在将下令 传到shell去之前,%已经被扩展为当前的文件名。有关单引号和双引号的区别可以参考这里,简单的说就是单引号会将其内部的内容原封不动的传给下令 ,但是双引号会睁开 一些内容,比如变量,转义字符等。

当然,也可以像前面一样将它映射为一个简单的下令 并添加到.vimrc中:

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

注意 :这里不再必要 把输出重定向到

  1. /dev/null
复制代码
中。

写在末端

至此,借助Vim强大 的机动 性,实现了两种方案,可以在以平常 用户启动的Vim中保存需root权限的文件。两者的原理雷同 ,都是利用 了Vim可以实行 外部下令 这一特性,区别在于利用 不同的shell下令 。假如 你还有别的 的方案,欢迎给我留言。

(全文完)

feihu

2014.07.30 于 Shenzhen


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

avatar 123457389 | 2021-9-9 19:38:23 | 显示全部楼层
admin楼主,您主治大夫在到处找您呢!
回复

使用道具 举报

avatar 123457466 | 2021-9-13 00:18:54 | 显示全部楼层
顶一下,收藏了!
回复

使用道具 举报

avatar 空城乱人心乱 | 2021-9-19 05:47:28 | 显示全部楼层
帖子好乱!
回复

使用道具 举报

avatar 万胜 | 2021-9-24 17:18:00 | 显示全部楼层
admin楼主,我告诉你一个你不知道的的秘密,有一个牛逼的网站,影视频道的网站所有电影和连续剧都可以免费看的。访问地址:http://tv.mxswl.com
回复

使用道具 举报

avatar auqsio7413820 | 2021-10-6 05:49:45 | 显示全部楼层
admin楼主,我告诉你一个你不知道的的秘密,有一个牛逼的源码论坛他的站点都是商业源码,还是免费下载的那种!特别好用。访问地址:http://www.mxswl.com 猫先森网络
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则