106

Suppose I have a file called file:

$ cat file
Hello
Welcome to
Unix

I want to add and Linux at the end of the last line of the file. If I do echo " and Linux" >> file will be added to a new line. But I want last line as Unix and Linux

So, in order to work around this, I want to remove newline character at the end of file. Therefore, how do I remove the newline character at the end of file in order to add text to that line?

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
Pandya
  • 23,898
  • 29
  • 92
  • 144

5 Answers5

101

If all you want to do is add text to the last line, it's very easy with sed. Replace $ (pattern matching at the end of the line) by the text you want to add, only on lines in the range $ (which means the last line).

sed '$ s/$/ and Linux/' <file >file.new &&
mv file.new file

which on Linux can be shortened to

sed -i '$ s/$/ and Linux/' file

If you want to remove the last byte in a file, Linux (more precisely GNU coreutils) offers the truncate command, which makes this very easy.

truncate -s -1 file

A POSIX way to do it is with dd. First determine the file length, then truncate it to one byte less.

length=$(wc -c <file)
dd if=/dev/null of=file obs="$((length-1))" seek=1

Note that both of these unconditionally truncate the last byte of the file. You may want to check that it's a newline first:

length=$(wc -c <file)
if [ "$length" -ne 0 ] && [ -z "$(tail -c -1 <file)" ]; then
  # The file ends with a newline or null
  dd if=/dev/null of=file obs="$((length-1))" seek=1
fi
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
  • 22
    Much better [way to remove a trailing newline](https://stackoverflow.com/a/1654042/2388257#how-can-i-delete-a-newline-if-it-is-the-last-character-in-a-file) is `perl -pi -e 'chomp if eof' myfile`. Compared to `truncate` or `dd` it not gonna leave you with a broken file if `myfile` had actually no trailing newlines. – Hi-Angel May 27 '19 at 13:24
  • 5
    @Hi-Angel May I recommend writing that as an answer? I think that would be a very good answer. – Simon Forsberg Sep 12 '19 at 13:03
59

You can achieve this with perl as:

perl -pi -e 'chomp if eof' myfile

Compared to truncate or dd this not gonna leave you with a broken file if myfile had actually no trailing newlines.

(the answer is constructed from the comment, and based on this answer)

Hi-Angel
  • 4,778
  • 4
  • 28
  • 45
  • Thank-you! This conditional method of removing is trailing newline is perfect. – xer0x Nov 04 '19 at 18:56
  • Best answer. Too bad for everyone that you were late to the party. – webb Dec 12 '20 at 00:14
  • 1
    best answer! Also to make this easy to use, I just defined a little function like this: `function chomp() { perl -p -e 'chomp if eof' }`. Now I can strip a new line with a pipe like this: `cat /tmp/file | chomp`. – Chris Jun 20 '21 at 23:27
57

Though, you can remove newline character from all lines by using tr -d '\n':

$ echo -e "Hello"
Hello
$ echo -e "Hello" | tr -d '\n'
Hello$

You can remove the newline character at the end of file using following easy way:

  1. head -c -1 file

From man head:

    -c, --bytes=[-]K
              print the first K bytes of each file; with the leading '-',
              print all but the last K bytes of each file
  1. truncate -s -1 file

from man truncate:

    -s, --size=SIZE
              set or adjust the file size by SIZE
SIZE is an integer and optional unit (example: 10M is 10*1024*1024). Units are K, M, G, T, P, E, Z, Y (powers of 1024) or KB, MB, ... (powers of 1000). SIZE may also be prefixed by one of the following modifying characters: '+' extend by, '-' reduce by, '' at least, '/' round down to multiple of, '%' round up to multiple of.
SebMa
  • 1,941
  • 4
  • 22
  • 37
Pandya
  • 23,898
  • 29
  • 92
  • 144
  • is `head -c -1 file | tee file` safe? Wouldn't `tee` truncate the file before starting? – iruvar Jan 11 '16 at 17:14
  • 1
    @1_CR Indeed. The two sides of the pipe start in parallel, it's a matter of who wins the race. Since `tee` only has to open the file, whereas `head` has to read and write its contents, `tee` will in practice win the race except sometimes for very small files. – Gilles 'SO- stop being evil' Jan 11 '16 at 22:46
  • 7
    This doesn't remove last newline, it remove all newlines. IMO quite a big difference. – Hi-Angel May 27 '19 at 13:16
  • 1
    Solution 2 should be the accepted answer. If your file is huge you really do not want to read the full file. – Ole Tange Dec 17 '20 at 19:28
5

Here's one way with sed -- on the last ($) line of the file, search and replace anything and everything (.*) with "whatever you matched" followed by " and Linux":

sed '$s/\(.*\)/\1 and Linux/' file

An even simpler solution, courtesy of Isaac, is:

sed '$s/$/ and Linux/' file

This replaces the (symbolic) end-of-line with the given text.

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
2
perl -0pi -e "s/\R\z//g" file

Works for "\r" (MAC), "\r\n" (Windows) and "\n" (Linux). For repeated newlines (any tipe) at end of file you can do:

perl -0pi -e "s/\R*\z//g" file
Mario Palumbo
  • 175
  • 12