11

I can do cat file.txt to get the contents of a file but I also want to tack on a final line of my own choosing.

I tried piping (cat file.txt ; echo "My final line") | but only the final line is getting passed through the pipe. How can I join the cat and final line?

Edit for a point of clarification: I do not wish to modify the file itself. I am aware that if this were the case I could do echo "My final line" >> file.txt or echo "My final line" | tee -a file.txt but I am only trying to do the append within the context of this particular command so I can pipe in the concatenation of file.txt and "My final line".

  • 1
    Maybe something like echo "My final line" >> file.txt? – edwinksl Oct 24 '17 at 14:06
  • I don't want to actually append the line to the file object, just in the command / piping. I already know that I can append the line with >> if I wanted to edit the file itself. – DoubleBass Oct 24 '17 at 14:09
  • 11
    Have you accidentally erased file.txt? Your pipe snippet should work. – Bracken Oct 24 '17 at 14:15
  • @DoubleBass: Mathieu Mitchell's answer is a better one, as it doesn't modify the file (either in-memory or on disk), but instead utilizes a feature of a built-in command. – Bryan Boettcher Oct 24 '17 at 17:26
29

You can leverage cat's ability to read from stdin combined with it's ability to read multiple files to achieve this.

~$ cat file.txt
Hello from file.txt

~$ echo "My final line" | cat file.txt -
Hello from file.txt
My final line

You can also prepend a line, as such:

~$ echo "My final line" | cat - file.txt
My final line
Hello from file.txt

Note that you are not limited to a single line. cat will read from stdin until it reaches EOF. You can pass the output from curl, for example, to prepend or append to the output of cat.

~$ curl -s http://perdu.com | cat file.txt -
Hello from file.txt
<html><head><title>Vous Etes Perdu ?</title></head><body><h1>Perdu sur l'Internet ?</h1><h2>Pas de panique, on va vous aider</h2><strong><pre>    * <----- vous &ecirc;tes ici</pre></strong></body></html>
  • 1
    (cat file.txt ; echo "My final line") | … would also do it. But using cat for what it was designed for is better +1. – ctrl-alt-delor Oct 24 '17 at 21:30
  • @ctrl-alt-delor: Sub-shells also have the disadvantage of an additional process to fork which is relatively expensive. Try for example echo "$$" "$BASHPID" | head -q -n 1 /proc/mounts - | cat vs. ( head -q -n 1 /proc/mounts; echo "$$" "$BASHPID" ) | cat or even { head -q -n 1 /proc/mounts; echo "$$" "$BASHPID"; } | cat. – David Foerster Oct 25 '17 at 12:48
11
sed -e '$aMy final line' file.txt

From man sed the option -e

-e script, --expression=script
    add the script to the commands to be executed

$ matches the last line and a appends the string.

If you wanted to permanently append the line to the file, use -i

-i[SUFFIX], --in-place[=SUFFIX]
    edit files in place (makes backup if SUFFIX supplied)

Changing the command to

sed -i -e '$aMy final line' file.txt
  • 1
    Use single quotes and you don't need the backslash. – Wildcard Oct 25 '17 at 4:10
8

For appending a line to a file, you can just use shell append redirection operator, >> (the file will be open(2)-ed with O_APPEND flag):

echo 'My final line' >>file.txt

Now, if you want just to view the content of the file with a final line appended, i would use cat with two arguments:

  • First, your file obviously, let's say file.txt
  • Second argument would be the string of your choice, and to pass the string as a filename (as cat only deals with files) you can leverage process substitution, <(), which would return a file descriptor (/proc/self/fd/<fd_number>).

Putting these together:

cat file.txt <(echo 'My final line')

If you want the output to be paged, assuming less is your favorite pager:

less file.txt <(echo 'My final line')
  • <() works for bash, but what other shells does it work for? Ksh? Dash? – jpaugh Oct 24 '17 at 17:26
  • 1
    @jpaugh ksh, zsh -- Yes, dash -- No. – heemayl Oct 24 '17 at 17:58
  • This modifies the original. – ctrl-alt-delor Oct 24 '17 at 21:31
7

It was already clarified in the comments to the question, but adding it again as an answer here.

The command noted in the question,

(cat file.txt ; echo "My final line") | other command

works as is expected – all the output from the subshell formed by the parentheses is piped to the second command.

If the file doesn't end with a new line, the echoed string is appended to the last line – this is common with all the other solutions here, and can be solved by adding another (empty) echo before.

  • 1
    If the file doesn't end with a newline, I'd use awk: awk 1 file.txt; echo "My final line". awk 1 file is a nice trick to compensate for missing EOL at the end of the file. – muru Oct 25 '17 at 3:29
  • If the file doesn't end with a new line, you can also just use echo "\nMy final line" without having to depend on awk – bfred.it May 31 at 8:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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