321

I am writing a bash script to look for a file if it doesn't exist then create it and append this to it:

Host localhost
    ForwardAgent yes

So "line then new line 'tab' then text" I think its a sensitive format. I know you can do this:

cat temp.txt >> data.txt

But it seems weird since its two lines. Is there a way to append that in this format:

echo "hello" >> greetings.txt

10 Answers 10

560
# possibility 1:
echo "line 1" >> greetings.txt
echo "line 2" >> greetings.txt

# possibility 2:
echo "line 1
line 2" >> greetings.txt

# possibility 3:
cat <<EOT >> greetings.txt
line 1
line 2
EOT

If sudo (other user privileges) is needed to write to the file, use this:

# possibility 1:
echo "line 1" | sudo tee -a greetings.txt > /dev/null

# possibility 3:
sudo tee -a greetings.txt > /dev/null <<EOT
line 1
line 2
EOT
  • 2
    @TheLegend That is called a "here document". Have a look at that paragraph in the man page. – Hauke Laging May 27 '13 at 15:00
  • 1
    One more possibility is ( echo "line 1" ; echo "line 2" ) >>greetings.txt. – ott-- May 27 '13 at 15:38
  • 2
    @ott-- You don't need a real subshell (i.e. can save one new process), this is enough: { echo "line 1" ; echo "line 2"; } >>greetings.txt – Hauke Laging May 27 '13 at 16:10
  • 2
    whts the difference between EOT and EOL? – cikatomo Jan 9 '16 at 18:34
  • 15
    @cikatomo In cat <<EOT the EOT is just a random string. Could be cat <<FOO, too. – Hauke Laging Jan 9 '16 at 20:37
60
printf '%s\n    %s\n' 'Host localhost' 'ForwardAgent yes' >> file.txt

Or, if it's a literal tab that you want (rather than the four spaces in your question):

printf '%s\n\t%s\n' 'Host localhost' 'ForwardAgent yes' >> file.txt

You can achieve the same effect with echo, but exactly how varies from implementation to implementation, whereas printf is constant.

36
echo -e "Hello \nWorld \n" >> greetings.txt
16

Another approach is to use tee

tee -a ~/.ssh/config << END
Host localhost
  ForwardAgent yes
END

A few choice lines from tee's man page:

The tee utility copies standard input to standard output, making a copy in zero or more files.

-a - Append the output to the files rather than overwriting them.

6

SED can append a line to the end of a file like so:

sed -i '$ a text to be inserted' fileName.file
$ selects end of file, the a tells it to append, and after this comes the text that is to be inserted. Then of course the file name.


Source: http://www.yourownlinux.com/2015/04/sed-command-in-linux-append-and-insert-lines-to-file.html

==========EDIT============

Does this approach have any added benefit than other solutions?
Yes, this approach has the added benefit of appending to any files return in a search, such as this: find . -name "*.html" -exec sed -i '$ a </html>' {} \;

I used the above example to insert the ending html tag that was missing on every html page within a number of directories.

===================================

  • 1
    If you would show the syntax for appending multiple lines to a file, then this would be an answer to the question (although not a very useful one).  All the other answers simply write the new text.  This answer reads the entire file and rewrites it, plus the added text.  Does this approach have any benefit over the others? – G-Man Says 'Reinstate Monica' Mar 18 '16 at 20:09
  • This only works with GNU sed. BSD sed bails with the error: command a expects \ followed by text. So don't use this for a scripted solution; it's liable to break. (Or do it properly as the BSD required syntax is POSIX compatible and will work on GNU sed as well. – Wildcard Mar 18 '16 at 20:28
  • The other answers can be used with find as follows: find . -name "*.txt" -exec sh -c 'printf "%s\n\t%s\n" "Host localhost" "ForwardAgent yes" >> "$1"' sh {} ";". – G-Man Says 'Reinstate Monica' Mar 19 '16 at 4:12
  • 1
    This is a very good solution, as it does not do stream redirection (>, >>) and thus does not suffer from their problems such as running sudo echo 'something' > /file. For me it perfectly allows to append a line to a file in lxd container like that: lxc exec c sed -- '$ a newline' /myfile. – Draco Ater Aug 23 '16 at 19:19
  • The echo "a new line" >> foo.file will not create a new line when the file is not end of new line, but sed -i '$ a a new line' foo.file will do, so sed is better especially you want always append a new line to the file. – zhouji Sep 12 '16 at 10:27
1

I used sed because it can be used with sudo. For example:

sudo sed -i '$ a text to be inserted' fileName.file 

the alternative is very ugly like :

sudo bash -c "echo a text to be inserted >> fileName.file"  

and even uglier when done with ssh.

  • 1
    Why was this answer downvoted? This looks like the solution I need. Is there any problem with it? If not, I'll use it and upvote it. – MountainX for Monica Cellio Jul 23 '16 at 8:20
  • Does your sed -i not take an extension as argument? Your example may have incorrect parameters. – protometa Jan 4 '17 at 19:57
1

Another one liner is:

echo "Greetings 1" >> greetings.txt && echo "Greetings 2" >> greetings.txt

I'd prefer the -e option thought, as it gives more control:

echo -e "Greeting 1\nGreetings 2\n" >> greetings.txt
1

One can emulate cat >> out.txt with either Perl or Python to achieve same effect. Perl:

perl -e 'open(fh,">>","./out.txt");while(<>){printf(fh "%s",$_)};close(fh);'

And Python:

python -c 'import sys;f=open(sys.argv[1],"a");l=[i for i in sys.stdin];f.write("".join(l))' out.txt 

Note that for python you'll have to hit Ctrl+D twice. See related question on stackoverflow for more info.

1

Here is an example to append multiple lines in a file:

{
        echo '  directory "/var/cache/bind";'
        echo '  listen-on { 127.0.0.1; };'
        echo '  listen-on-v6 { none; };'
        echo '  version "";'
        echo '  auth-nxdomain no;'
        echo '  forward only;'  
        echo '  forwarders { 8.8.8.8; 8.8.4.4; };'
        echo '  dnssec-enable no;'
        echo '  dnssec-validation no;'
} >> your_file.txt
0

In addition to main answer, in case the file needs super user permissions, just adding sudo in front of echo won't work.

This is because shell breaks the commands and though echo did run as root, but >> ran with normal privileges.

This will work for super user: sudo su -c "echo 'Line 3' >> greetings.txt"

  • You don't need the su here (sudo su is not good). But you're right in that you need something do manage the shell redirection; perhaps sudo sh -c "echo stuff >> file.txt". No net saving but a better practice. – roaima Aug 8 at 13:51

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