13

I always do this to append text to a file

echo "text text text ..." >> file
# or
printf "%s\n" "text text text ..." >> file

I wonder if there are more ways to achieve the same, more elegant or unusual way.

2
  • 3
    As I already said, it's not only that. echo "a\nb" will print something different than printf "%s\n" "a\nb", in ~all the shells but bash. You cannot assume that the two are similar.
    – mosvy
    Feb 14 '20 at 5:47
  • 1
    Note that you can group commands together (a ; b ; c) >> file Feb 15 '20 at 13:44
25

I quite like this one, where I can set up a log file at the top of a script and write to it throughout without needing either a global variable or to remember to change all occurrences of a filename:

exec 3>> /tmp/somefile.log
...

echo "This is a log message" >&3
echo "This goes to stdout"
echo "This is written to stderr" >&2

The exec 3>dest construct opens the file dest for writing (use >> for appending, < for reading - just as usual) and attaches it to file descriptor #3. You then get descriptor #1 for stdout, #2 for stderr, and this new #3 for the file dest.

You can join stderr to stdout for the duration of a script with a construct such as exec 2>&1 - there are lots of powerful possibilities. The documentation (man bash) has this to say about it:

exec [-cl] [-a name] [command [arguments]] If command is specified, it replaces the shell. [...] If command is not specified, any redirections take effect in the current shell [...].

0
12

Here are few other ways to append text to a file.

  1. Using tee

    tee -a file <<< "text text text ..."
    
  2. Using awk

    awk 'BEGIN{ printf "text text text ..." >> "file" }'
    
  3. Using sed

    sed -i '$a text text text ...' file
    sed -i -e "\$atext text text ..." file
    

Sources:

1
  • 2
    sed -i does not so much append as overwrite with an extended version. Normally not much of an issue, but it can be if the file is sparse, linked, or actively being read.
    – David G.
    Feb 16 '20 at 12:44
10

Using a here-document approach:

cat <<EOF >> file
> foo
> bar
> baz
> EOF

Tests:

$ cat file
aaaa
bbbb

$ cat <<EOF >> file
> foo
> bar
> baz
> EOF

$ cat file
aaaa
bbbb
foo
bar
baz
4
  • 5
    Why downvote? This is a valid answer tho.
    – annahri
    Feb 14 '20 at 14:50
  • @annahri See updated answer with tests. Feb 14 '20 at 15:28
  • 1
    This is very, very useful in scripts. Feb 15 '20 at 13:45
  • @ThorbjørnRavnAndersen Thank you :) Feb 15 '20 at 13:46
4

See dd(1) man page:

dd conv=notrunc oflags=append bs=4096 if=myNewData of=myOldFile
12
  • This is creative, but can you use a line of string instead of an input file?
    – annahri
    Feb 14 '20 at 14:23
  • @annahri yes certainly, dd conv=notruct oflag=append of=destination <<<'Some string of text'
    – roaima
    Feb 14 '20 at 15:42
  • 1
    @roaima that's shell dependent though. Not all shells support the <<< herestring construct. I have no idea what dd would do in those cases, would it be safe?
    – terdon
    Feb 15 '20 at 16:04
  • 1
    @annahri. My bad: I scrolled down under "Each CONV symbol may be:" on the man page, and missed the bit where the list changes to "Each FLAG symbol may be:". Feb 15 '20 at 17:20
  • 1
    I tested dd with <<< in dash. It throws "Syntax error: redirection unexpected" with status 2, so dd itself is not even invoked. Feb 15 '20 at 17:37
3

Using the Unix file editors. Both GNU and BSD version.

Using ed(1) with printf

printf '%s\n' '$a' 'foo bar baz' . w | ed -s file.txt

The bash specific but more cryptic syntax using the $' ' shell quoting and a herestring

ed -s file.txt <<< $'$a\nfoo bar baz\n.\nw'

Using ex(1) with printf

printf '%s\n' '$a' 'foo bar baz' . x | ex -s file.txt

The bash specific but more cryptic syntax $' ' shell quoting and a herestring

ex -s file.txt <<< $'$a\nfoo bar baz\n.\nx'
2
  • 1
    ed, ex, and other text editors do not so much append as overwrite with an extended version. Normally not much of an issue, but it can be if the file is sparse, linked, or actively being read.
    – David G.
    Feb 16 '20 at 12:51
  • @DavidG. Thank you for that wonderful comment.
    – Jetchisel
    Feb 16 '20 at 13:42
1
cat >> file
first line
second line
...
last line

Hit Enter at the last line then Ctrl + D.

1
  • I often use this now to copy-paste things into a file quickly.
    – annahri
    Aug 25 at 2:36

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