Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am getting countless

warning: no newline at end of file

From some code that was last edited in Windows.

In Linux, how can I fix all these cpp/h files and add a new line to the end of every file that does not have a new line?

I've been trying to use sed:

find . \( -name "*.cpp" -o -name "*.h" -o -name "*.hpp" \) -print | xargs sed -i -e "$G"

But I haven't gotten it working yet.

share|improve this question
There is a command, dos2unix, that might be of assistance to you. It converts the CR+LF line ending of windows to the LF line ending of linux. Another option is to just echo (append - i.e. >> ) a newline to every relevant file. – cyberx86 Dec 11 '11 at 2:29
The problem is there are far too many files to find them by hand. – Zeno Dec 11 '11 at 2:32
Use find in that case, as with your example, just switch up sed for a different command (of course, try that command on a single file first). Both echo and dos2unix work fine with find. – cyberx86 Dec 11 '11 at 2:35
I'm trying find . \( -name "*.cpp" -o -name "*.h" -o -name "*.hpp" \) -print | xargs echo >> but that gives me error -bash: syntax error near unexpected token newline'` – Zeno Dec 11 '11 at 2:39
Hmm, I don't see a 'newline' in your command, so I guess that SF removed it. Just use echo without any arguments - it automatically adds a newline (and of course, test it out on one file before you do that - wouldn't want to see hundreds of files improperly edited) - so echo >> (note there is just a space between echo and >> in my command) – cyberx86 Dec 11 '11 at 2:47
up vote 2 down vote accepted

In the absence of dos2unix - which would be the ideal way, try:

find . \( -name "*.cpp" -o -name "*.h" -o -name "*.hpp" \) -print0 | xargs -0 -iFILE sh -c 'echo >> FILE'


find . -type f \( -name "*.cpp" -o -name "*.h" -o -name "*.hpp" \) -exec sh -c 'echo >> {}' \;

Note that redirection is always a problem - the replacement doesn't occur as desired without launching a new shell.

Since your question was about 'sed', you could also do it as:

find . \( -name "*.cpp" -o -name "*.h" -o -name "*.hpp" \) -print0 | xargs -0 sed -i -e '$a\

(That is a literal new line character - not a \n or anything else - probably best done as copy and paste - as it might be rather hard to type in :).

share|improve this answer
The first one seems to insert an "h" into the file? This would break my code. – Zeno Dec 11 '11 at 3:43
Sorry - typo - I used 'h' to test it since I was losing track of the new lines being entered - will have it edited in a second. – cyberx86 Dec 11 '11 at 3:46
Thanks, this worked. – Zeno Dec 11 '11 at 3:49
dos2unix did not affect all files. I used find -type f -exec dos2unix "{}" \+ It did convert existing line endings to linux, but it did not add newlines to the ends of files that didn't have them. By the way I think you make literal newline by typing ctrl-v and then ctrl-m in linux. See – Buttle Butkus Dec 13 '15 at 10:13
Actually, now I'm not sure that dos2unix failed. I based that judgment on using this code to search for files missing final newlines: find -type f -exec sh -c '[ -z "$(sed -n "\$p" "$1")" ] && echo "$1"' _ {} \; But it seems to be wrong. The 2nd and 3rd answers on that page give me no matches. ( pcregrep -LMr '\n$' . and -print0 | xargs -0 -L1 bash -c 'test "$(tail -c 1 "$0")" && echo "No new line at end of $0"' ) So now I don't know. – Buttle Butkus Dec 13 '15 at 10:29
find . \( -name "*.cpp" -o -name "*.h" -o -name "*.hpp" \) -print | xargs dos2unix {}
share|improve this answer
[root@server23 ~]# dos2unix -bash: dos2unix: command not foundThis server doesn't have that nor do I have permission to install dos2unix. – Zeno Dec 11 '11 at 3:34
If you are root you should be able to install it – ckliborn Dec 11 '11 at 3:35
Note that this will break badly on files that have spaces in the name or other oddities. Use "-print0" and "xargs -0" or just use the "-exec dos2unix '{}' +" arguments. Also, xargs does not take '{}' arguments. – Sean Reifschneider Dec 11 '11 at 3:37
find . ( -name ".cpp" -o -name ".h" -o -name "*.hpp" ) -print | xargs echo >> {} – ckliborn Dec 11 '11 at 3:37
@Zeno: If you can't install it, you can grab the package that has it, and use "rpm2cpio <PACKAGE-FILENAME | cpio -ivd" to extract it, then just run it from the extracted directory. For debian packages you need to use "ar xv PACKAGE-FILENAME" which then gives you a tar file that you can extract with "tar xvfz data.tar.gz". These will result in a "dos2unix" file that you could run with the full path to this extracted file ("find | grep dos2unix" if you can't find it). – Sean Reifschneider Dec 11 '11 at 3:44

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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