0

I opened a large file, didn't make a modification, and pressed :w. Then Vim was frozen for a while. Was it simply rewriting the whole file? Is it possible to make it understand that there was no change so that it could just quit? To generalize a little bit, is it possible to let it not rewrite the whole file if I only modified a small part of it?

  • I think :exit (:x) will do what you want, but only if you also want to quit. – D. Ben Knoble Jan 13 at 22:24
  • @D.BenKnoble Yeah, and if you modify one byte, :x would freeze. – Cyker Jan 13 at 23:06
  • Well sure. There were changes. – D. Ben Knoble Jan 13 at 23:07
5

Instead of :write you should use :update. According to vim's help:

                            *:up* *:update*
:[range]up[date][!] [++opt] [>>] [file]
            Like ":write", but only write when the buffer has been
            modified.  {not in Vi}

As stated, this will only write out the file to disk if there have been modifications known to vim. You would use :write instead if, for example, you have changed or corrupted the file on disk and would like to write vim's buffer contents again.

  • Sounds better than :x. But what if I modified a byte but don't want Vim completely rewrite the whole file? – Cyker Jan 14 at 0:05
4

I did a short check with strace on Linux. I edit README.md and add one character to the last line.

Here is the relevant part:

01: stat("README.md", {st_mode=S_IFREG|0644, st_size=5986, ...}) = 0
02: stat("README.md~", {st_mode=S_IFREG|0644, st_size=5988, ...}) = 0
03: unlink("README.md~")                    = 0
04: rename("README.md", "README.md~")       = 0
05: open("README.md", O_WRONLY|O_CREAT, 0644) = 3
06: ftruncate(3, 0)                         = 0
07: write(3, "![Vim Logo](https://github.com/v"..., 5987) = 5987
08: fsync(3)                                = 0
09: stat("README.md", {st_mode=S_IFREG|0644, st_size=5987, ...}) = 0
10: stat("README.md", {st_mode=S_IFREG|0644, st_size=5987, ...}) = 0
11: fchmod(3, 0100644)                      = 0
12: close(3)                                = 0

The lines 02-04 show how the backup file is created. Here the original file is moved to README.md~ (a already existing README.md~ is deleted in in line 03).

Then the new file README.md is written line 05-12. In line 06 the call to ftruncate truncates the file to zero (irrelevant here, as this is a new file) and then the complete content is written (5987 byte).

Note that depending on the option backupcopy, the backup file README.md~ might be written, instead of just renaming README.md to README.md~.

Here with set nobackup:

01: open("README.md", O_WRONLY|O_CREAT, 0644) = 3
02: ftruncate(3, 0)                         = 0
03: write(3, "![Vim Logo](https://github.com/v"..., 5987) = 5987
04: fsync(3)                                = 0
05: stat("README.md", {st_mode=S_IFREG|0644, st_size=5987, ...}) = 0
06: stat("README.md", {st_mode=S_IFREG|0644, st_size=5987, ...}) = 0
07: fchmod(3, 0100644)                      = 0
08: close(3)                                = 0

Here no backup file is created, but also the file README.md is first truncated to size zero and then the complete content is written (5987 byte).

My conclusion: Vim always writes the entire file.

I'm not aware that there is any option to just write changed parts. Also this would be not trivial to implement.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.