insert EOF statement before the last line of file

To keep the same sort of here-document format and to insert the given text immediately before the last line of the file, try ed!

ed -s /etc/security/limits.conf << EOF
$ i
*    soft     nproc       65535    
*    hard     nproc       65535   
*    soft     nofile      65535   
*    hard     nofile      65535
root soft     nproc       65535
root hard     nproc       65535
root soft     nofile      65535
root hard     nofile      65535
.
wq
EOF

This sends a sequence of commands to ed, all in a here-document. We address the last line in the file with $ and say that we would like to insert some text. The text follows, just as in your example; once we're done with the inserted text, we tell ed we're done with a single period (.). Write the file back to disk and then quit.

If you wanted to collapse the $ i to $i you'd want to escape the dollar sign or use a quoted here-document (ed -s input << 'EOF' ...) to prevent $i from expanding to the current vale of the i variable or empty if there's no such variable set.


You can use ex (which is a mode of the vi editor) to accomplish this.

You can use the :read command to insert the contents into the file. That command takes a filename, but you can use the /dev/stdin pseudo-device to read from standard input, which allows you to use a <<EOF marker.

The :read command also takes a range, and you can use the $- symbol, which breaks down into $, which indicates the last line of the file, and - to subtract one from it, getting to the second to last line of the file. (You could use $-1 as well.)

Putting it all together:

$ ex -s /etc/security/limits.conf -c '$-r /dev/stdin' -c 'wq' <<EOF
*    soft     nproc       65535    
*    hard     nproc       65535   
*    soft     nofile      65535   
*    hard     nofile      65535
root soft     nproc       65535
root hard     nproc       65535
root soft     nofile      65535
root hard     nofile      65535
EOF

The -s is to make it silent (not switch into visual mode, which would make the screen blink.) The $-r is abbreviated (a full $-1read would have worked as well) and finally the wq is how you write and quit in vi. :-)


UPDATE: If instead of inserting before the last line, you want to insert before a line with specific contents (such as "# End of file"), then just use a /search/ pattern to do so.

For example:

$ ex -s /etc/security/limits.conf -c '/^# End of file/-1r /dev/stdin' -c 'wq' <<EOF
...
EOF