Short ways of adding a newline to the end of a file if, and only if, there isn’t already one there tend to rely on tricks. For example:
tail -c1 file.txt | read || printf "\n" >> file.txt
The tail -c1
gets the last character of the file. That’s then piped to read
, which is normally used to gather a line of input and split it into words for later processing. But this one-liner cares only about read
’s exit code, which is a success if the input ends with a newline and a failure if it doesn’t. The success or failure is then used by the short-circuit OR operator, ||
to determine whether the next command is executed. The final command, printf "\n" >> file.txt
, outputs a newline and appends it to the file.
So, if the last character of the file is not a newline, read
fails, the printf
command is run, and a newline is appended to the file. If the last character of the file is a newline, read
succeeds, the printf
command is not run, and the file is left unchanged.
There’s also a sed
command for this:
sed -i '' '$ a\' file.txt
The -i ''
switch tells sed
to edit the file in place and not to make a backup of the original file. The $
part of the command tells sed
to act on the last line of the file, and the a\
part tells it to append nothing. As with the sed
command in my previous answer, this works because of sed
’s prejudice against lines that don’t end with a newline. When it appends “nothing” to the last line, it also tacks on a newline. Frankly, I don’t see why you’d want to use this if you didn’t like the earlier sed
command.
Finally, we can use Perl:
perl -pe 's/$/\n/ if substr($_, -1) != "\n"' file.txt
This goes through every line in the file adds a newline if the last character of the line isn’t already a newline. This is pretty inefficient, as it looks at all the lines when all we really care about is the last one, but at least it doesn’t rely on tricks. How readable it is depends on how readable you think Perl is.
I haven't written enough Ruby to feel comfortable doing this in that language, although I suspect a Ruby solution would look a lot like the Perl solution. An equivalent Python script would probably be easier to read than any of these—even if you don't know Python—but it would also be distinctly longer.
What the “best” solution is depends on what you feel comfortable with and what you think you’ll remember when you go back to look at your code later.