在vim中原地编辑文件

8

通常情况下,你并不会在vim中直接编辑一个文件。如果你运行vim foo,编辑、写入并退出,vim会删除foo并创建一个新的文件和一个名为foo的新链接。但是,如果这个文件有多个链接,那么vim实际上会修改这个文件。例如:

$ ls -i foo
19428852 foo
$ vi foo
$ ls -i foo
19428857 foo
$ ln foo bar
$ vi bar
$ ls -i bar
19428857 bar

我一直在寻找一种编辑文件的方法,似乎有两个选择。使用ed或使用vim但要确保在编辑之前至少有两个链接指向该文件。我想这是一个学术问题,因为如果只有一个链接,vim创建一个新文件也不重要,而且如果在编辑过程中创建链接,vim似乎会处理得当。但我很好奇:是否可能让vim总是编辑文件而不会创建新文件?

一些原因为什么这很重要...创建新文件并交换链接的优点:防止其他程序看到部分写入的文件。原地编写文件的优点:fileschanged程序(使用fam)似乎更快地看到更改(立即,而不是删除文件和交换链接时出现大约6秒的延迟,由于某种原因...这可以说是fam或fileschanged中的特殊情况)。 - Don Hatch
如果一个单独的文件被绑定挂载,例如 - 到一个 Docker 容器中 - 那么通过创建一个新文件并交换链接来更改文件意味着绑定挂载仍然指向旧文件的 inode ID。直接在原地写入文件是解决方案。下面的答案帮助了我解决这个问题。 - Mark
3个回答

13

请查看backupcopy选项的帮助以及关于crontab的注意事项。简而言之,答案是

:set backupcopy=yes

1
谢谢。我发现文档不太清楚。“当文件是链接时,新文件将不是链接”。什么鬼?!每个链接都是链接,而访问文件的唯一方式就是通过链接! - William Pursell

3

诀窍在于告诉Vim使用备份文件,以便安全地覆盖原始文件,否则Vim将写入一个新文件,然后重命名它以替换原始文件。

然后告诉Vim将备份文件写入无处。这样,常规写命令将失败,必须强制写入。

:set noswapfile
:set backupcopy=yes
:set backupdir=''
:e big
(hit Crtl-C to stopo line count and syntax highlight)
(edit the file)
:w!

为了真正了解文件系统层面发生的情况,我使用了inotify工具:
inotifywait -m -r /path/to/my_test_dir/

但要小心,这种方法对于非常大的文件效果不好,例如,我试图使用此方法直接编辑一个10G的文件,结果得到了一个截断的1.5GB文件,其余数据丢失。Vim最终使用了将近2GB的RAM...

另一个选择是使用MMap函数,例如在Python命令行中。


2

快速谷歌搜索显示此链接 - 编辑文件的硬链接。控制该操作的命令是

set backupcopy=auto,breakhardlink

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接