How to add a newline to the end of a file?

Here you go:

sed -i -e '$a\' file

And alternatively for OS X sed:

sed -i '' -e '$a\' file

This adds \n at the end of the file only if it doesn’t already end with a newline. So if you run it twice, it will not add another newline:

$ cd "$(mktemp -d)"
$ printf foo > test.txt
$ sed -e '$a\' test.txt > test-with-eol.txt
$ diff test*
1c1
< foo
\ No newline at end of file
---
> foo
$ echo $?
1
$ sed -e '$a\' test-with-eol.txt > test-still-with-one-eol.txt
$ diff test-with-eol.txt test-still-with-one-eol.txt
$ echo $?
0

To recursively sanitize a project I use this oneliner:

git ls-files -z | while IFS= read -rd '' f; do tail -c1 < "$f" | read -r _ || echo >> "$f"; done

Explanation:

  • git ls-files -z lists files in the repository. It takes an optional pattern as additional parameter which might be useful in some cases if you want to restrict the operation to certain files/directories. As an alternative, you could use find -print0 ... or similar programs to list affected files - just make sure it emits NUL-delimited entries.

  • while IFS= read -rd '' f; do ... done iterates through the entries, safely handling filenames that include whitespace and/or newlines.

  • tail -c1 < "$f" reads the last char from a file.

  • read -r _ exits with a nonzero exit status if a trailing newline is missing.

  • || echo >> "$f" appends a newline to the file if the exit status of the previous command was nonzero.


Have a look:

$ echo -n foo > foo 
$ cat foo
foo$
$ echo "" >> foo
$ cat foo
foo

so echo "" >> noeol-file should do the trick. (Or did you mean to ask for identifying these files and fixing them?)

edit removed the "" from echo "" >> foo (see @yuyichao's comment) edit2 added the "" again (but see @Keith Thompson's comment)