你们中的许多人可能都见过这样一个命令,它允许您在需要root权限的文件上进行写入,即使您忘记使用sudo打开vim:
:w !sudo tee %
问题是我不知道这里到底发生了什么。
我已经想好了:w是这个
*: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 |:!|.
因此它将所有行作为标准输入传递。
这个sudo tee部分以管理员权限调用tee。
为了让所有人都能理解,%应该输出文件名(作为tee的参数),但我在帮助中找不到关于此行为的引用。
tl;有人能帮我分析一下这个命令吗?
在执行的命令行中,%代表当前文件名。这在:help cmdline special:
In Ex commands, at places where a file name can be used, the following
characters have a special meaning.
% Is replaced with the current file name.
正如你已经发现的,:w!cmd将当前缓冲区的内容通过管道传输到另一个命令。tee所做的是将标准输入复制到一个或多个文件,也复制到标准输出。因此,:w!sudotee%>/dev/null有效地将当前缓冲区的内容写入当前文件,同时作为根文件。另一个可用于此操作的命令是dd:
:w !sudo dd of=% > /dev/null
作为快捷方式,您可以将此映射添加到.virc中:
" Force saving files that require root permission
cnoremap w!! w !sudo tee > /dev/null %
使用以上选项,您可以键入:w<输入>将文件保存为根目录。
我想建议另一种解决“打开文件时忘记写sudo”问题的方法:
而不是接收拒绝的权限,并且必须键入:w!!,我发现如果文件所有者是root,那么使用一个条件vim命令来执行sudovim会更优雅。
这同样容易实现(甚至可能有更优雅的实现,我显然不是bash大师):
function vim(){
OWNER=$(stat -c '%U' $1)
if [[ "$OWNER" == "root" ]]; then
sudo /usr/bin/vim $*;
else
/usr/bin/vim $*;
fi
}
而且效果非常好。
这是一种比vim更以bash为中心的方法,所以不是每个人都喜欢它。
当然:
在某些用例中,它会失败(当文件所有者不是root用户,但需要sudo,但无论如何都可以编辑该函数)当使用vim只读取文件时(就我而言,我对小文件使用tail或cat),这是没有意义的
但我发现这带来了更好的开发用户体验,这是IMHO在使用bash时容易忘记的