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?
2 Answers
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?– CykerJan 14, 2019 at 0:05
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, " = 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, " = 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.
:exit
(:x
) will do what you want, but only if you also want to quit.:x
would freeze.