从下面的评论中可以看出,上述内容存在一些混淆。如果您想亲自了解在特定品牌的 Unix 上设置 Vim 时实际发生了什么,我建议您跟踪 Vim 在写入只读文件时所做的系统调用。如何做到这一点取决于您使用的是什么 Unix。在 Linux 上,这可能通过 eg 完成strace vim file(然后编辑文件,保存w!并退出)。
这是第一种情况(OpenBSD 上ktrace+的输出):kdump
13228 vim CALL chmod(0x19b1d94b4b10,0100644<S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH|S_IFREG>)
13228 vim NAMI "file"
13228 vim RET chmod 0
13228 vim CALL lseek(3,0x1000,SEEK_SET)
13228 vim RET lseek 4096/0x1000
13228 vim CALL write(3,0x19b1e0aa9000,0x1000)
这会更改文件的权限,使其可写(与S_IWUSR一起使用的标志chmod())并将缓冲区写入其中。
然后它设置原始权限:
13228 vim CALL fchmod(4,0100444<S_IRUSR|S_IRGRP|S_IROTH|S_IFREG>)
13228 vim RET fchmod 0
13228 vim CALL close(4)
13228 vim RET close 0
对于另一种情况:
它首先取消链接(删除)文件,然后重新创建它(在写入文件并稍后更改权限之前):
44487 vim CALL unlink(0x79fdbc1f000)
44487 vim NAMI "file"
44487 vim RET unlink 0
44487 vim CALL open(0x79fdbc1f000,0x201<O_WRONLY|O_CREAT>,0644<S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH>)
44487 vim NAMI "file"
44487 vim RET open 4
$ touch foo
$ chmod u-w foo
$ ls -li foo
60818465 -r--r----- 1 philip philip 0 Feb 25 10:24 foo
$ vi foo
$ # edit the file and save with :w!
$ ls -li foo
60818467 -r--r----- 1 philip philip 8 Feb 25 10:25 foo
请注意,inode 编号已更改,表明新文件与您编辑的文件不同。
仅供参考我目前的配置真的很短:
runtime! debian.vim
if has("syntax")
syntax on
endif
set tabstop=4
set autoindent
安装的 debian 软件包是:
vim 2:8.1.0875-1
vim-common 2:8.1.0875-1
vim-runtime 2:8.1.0875-1
vim-tiny 2:8.1.0875-1
*'cpoptions'* *'cpo'* *cpo*
'cpoptions' 'cpo' string (Vim default: "aABceFs",
Vi default: all flags)
...
*cpo-W*
W Don't overwrite a readonly file. When omitted, ":w!"
overwrites a readonly file, if possible.
当您
w!
在 Vim 中执行此操作时,实际发生的情况取决于文件的所有者。如果您(当前用户)是文件的所有者,Vim 会在重写文件之前将权限更改为可写。然后它会删除写入权限以将权限位恢复到从一开始的状态。
如果你不是该文件的所有者,但如果你在当前目录有写权限,Vim 会删除原文件并将文档写入一个同名的新文件中。然后,新文件将被分配与原始文件相同的权限,但归您所有。
Vim 在任何时候都不会获得更高的权限来写入文件。
上述机制是任何需要写入只读文件的程序必须从中选择的可用选项(即,在写入文件时临时更改权限,或删除文件并创建新文件),以及Vim 最终选择做什么可能最终取决于许多可配置的设置。
从下面的评论中可以看出,上述内容存在一些混淆。如果您想亲自了解在特定品牌的 Unix 上设置 Vim 时实际发生了什么,我建议您跟踪 Vim 在写入只读文件时所做的系统调用。如何做到这一点取决于您使用的是什么 Unix。在 Linux 上,这可能通过 eg 完成
strace vim file
(然后编辑文件,保存w!
并退出)。这是第一种情况(OpenBSD 上
ktrace
+的输出):kdump
这会更改文件的权限,使其可写(与
S_IWUSR
一起使用的标志chmod()
)并将缓冲区写入其中。然后它设置原始权限:
对于另一种情况:
它首先取消链接(删除)文件,然后重新创建它(在写入文件并稍后更改权限之前):
Vim 不能获得额外的权限。
:w!
只是覆盖了 internal选项,该'readonly'
选项可能已被设置,因为:-R
命令行选项或使用:view
而不是打开文件:edit
,或:setlocal readonly
对于后一种情况,文件写入仍然是可能的,因为 Vim(默认情况下)创建一个新文件,然后用它替换原始文件。这仍然取决于以允许这样做的方式设置的权限。
要在打开 Vim 的用户没有任何权限的情况下真正获得写入权限,
:w !sudo tee >/dev/null file
必须直接使用这个技巧,或者通过像SudoEdit这样的插件。您永远无法写入您没有写入权限的文件。但是,如果您对该目录具有写入权限,则可以删除该文件。
VIM 使用的技巧是删除文件并写入一个新文件。
通过检查前后的inode 编号,可以证明这是 VIM 使用的方法,无需读取源代码:
请注意,inode 编号已更改,表明新文件与您编辑的文件不同。
仅供参考我目前的配置真的很短:
安装的 debian 软件包是:
当 vim 处于 vi 兼容模式时,:w! 只会覆盖缓冲区的只读模式,但不会尝试来回更改文件权限,通过将不同的文件重命名为原始文件的名称来绕过权限,或者做其他业余时间的事情。
这是唯一正确的行为恕我直言 - 控制它的标志
W
来自cpoptions
/cpo
。来自:help cpo
::set compatible
将打开所有cpo
标志。您可以使用或仅更改W
标志。:set cpo+=W
set cpo-=W