I have trouble understanding a weird behavior: vi seems to add a newline (ASCII: LF, as it is a Unix (AIX) system) at the end of the file, when I did NOT specifically type it.
I edit the file as such in vi (taking care to not input a newline at the end):
# vi foo ## Which I will finish on the char "9" and not input a last newline, then `:wq`
123456789
123456789
123456789
123456789
~
~
## When I save, the cursor is just above the last "9", and no newline was added.
I expect vi to save it "as is", so to have 39 bytes: 10 ASCII characters on each of the first three lines (numbers 1 to 9, followed by a newline (LF on my system)) and only 9 on the last line (characters 1 to 9, no terminating newline/LF).
But it appears when I save it it is 40 bytes (instead of 39), and od shows a terminating LF:
# wc foo
4 4 40 foo ## I expected 39 here! as I didn't add the last newline
# od -a toto
0000000 1 2 3 4 5 6 7 8 9 lf 1 2 3 4 5 6
0000020 7 8 9 lf 1 2 3 4 5 6 7 8 9 lf 1 2
0000040 3 4 5 6 7 8 9 lf
0000050
## An "lf" terminates the file?? Did vi add it silently?
If I create the file with a printf doing exactly what I did inside vi, it works as expected:
# ## I create a file with NO newline at the end:
# printf "123456789\n123456789\n123456789\n123456789" > foo2
# wc foo2 ## This one is as expected: 39 bytes, exactly as I was trying to do above with vi.
3 4 39 foo ## As expected, as I didn't add the last newline
## Note that for wc, there are only three lines!
## (So wc -l doesn't count lines; it counts the [newline] chars... Which is rather odd.)
# root@SPU0WMY1:~ ## od -a foo2
0000000 1 2 3 4 5 6 7 8 9 lf 1 2 3 4 5 6
0000020 7 8 9 lf 1 2 3 4 5 6 7 8 9 lf 1 2
0000040 3 4 5 6 7 8 9
0000047 ## As expected, no added LF.
Both files (foo (40 characters) and foo2 (39 characters) appear exactly the same if I re-open them with vi...
And if I open foo2 (39 characters, no terminating newline) in vi and just do :wq
without editing it whatsoever, it says it writes 40 chars, and the linefeed appears!
I can't have access to a more recent vi (I do this on AIX, vi (not Vim) version 3.10 I think? (no "-version" or other means of knowing it)).
# strings /usr/bin/vi | grep -i 'version.*[0-9]'
@(#) Version 3.10
Is it normal for vi (and perhaps not in more recent version? Or Vim?) to silently add a newline at the end of a file? (I thought the ~ indicated that the previous line did NOT end with a newline.)
--
Edit: some additional updates and a bit of a summary, with a big thanks to the answers below :
vi silently add a trailing newline at the moment it writes a file that lacked it (unless file is empty).
it only does so at the writing time! (ie, until you :w, you can use :e to verify that the file is still as you openened it... (ie: it still shows "filename" [Last line is not complete] N line, M character). When you save, a newline is silently added, without a specific warning (it does say how many bytes it saves, but this is in most cases not enough to know a newline was added) (thanks to @jiliagre for talking to me about the opening vi message, it helped me to find a way to know when the change really occurs)
This (silent correction) is POSIX behavior! (see @barefoot-io answer for references)
vi
version or at least a clue about its origin by running the:ve
command.ex
manual page where the:ver
command is normally documented.