Unix command to prepend text to a file

UnixCommand LineUtilitiesPrepend

Unix Problem Overview


Is there a Unix command to prepend some string data to a text file?

Something like:

prepend "to be prepended" text.txt

Unix Solutions


Solution 1 - Unix

printf '%s\n%s\n' "to be prepended" "$(cat text.txt)" >text.txt

Solution 2 - Unix

sed -i.old '1s;^;to be prepended;' inFile
  • -i writes the change in place and take a backup if any extension is given. (In this case, .old)
  • 1s;^;to be prepended; substitutes the beginning of the first line by the given replacement string, using ; as a command delimiter.

Solution 3 - Unix

Process Substitution

I'm surprised no one mentioned this.

cat <(echo "before") text.txt > newfile.txt

which is arguably more natural than the accepted answer (printing something and piping it into a substitution command is lexicographically counter-intuitive).

...and hijacking what ryan said above, with sponge you don't need a temporary file:

sudo apt-get install moreutils
<<(echo "to be prepended") < text.txt | sponge text.txt

EDIT: Looks like this doesn't work in Bourne Shell /bin/sh


Here String (zsh only)

Using a here-string - <<<, you can do:

<<< "to be prepended" < text.txt | sponge text.txt

Solution 4 - Unix

This is one possibility:

(echo "to be prepended"; cat text.txt) > newfile.txt

you'll probably not easily get around an intermediate file.

Alternatives (can be cumbersome with shell escaping):

sed -i '0,/^/s//to be prepended/' text.txt

Solution 5 - Unix

This will work to form the output. The - means standard input, which is provide via the pipe from echo.

echo -e "to be prepended \n another line" | cat - text.txt

To rewrite the file a temporary file is required as cannot pipe back into the input file.

echo "to be prepended" | cat - text.txt > text.txt.tmp
mv text.txt.tmp text.txt

Solution 6 - Unix

If it's acceptable to replace the input file:

Note:

  • Doing so may have unexpected side effects, notably potentially replacing a symlink with a regular file, ending up with different permissions on the file, and changing the file's creation (birth) date.

  • sed -i, as in Prince John Wesley's answer, tries to at least restore the original permissions, but the other limitations apply as well.

Here's a simple alternative that uses a temporary file (it avoids reading the whole input file into memory the way that shime's solution does):

{ printf 'to be prepended'; cat text.txt; } > tmp.txt && mv tmp.txt text.txt

Using a group command ({ ...; ...; }) is slightly more efficient than using a subshell ((...; ...)), as in 0xC0000022L's solution.

The advantages are:

  • It's easy to control whether the new text should be directly prepended to the first line or whether it should be inserted as new line(s) (simply append \n to the printf argument).

  • Unlike the sed solution, it works if the input file is empty (0 bytes).


The sed solution can be simplified if the intent is to prepend one or more whole lines to the existing content (assuming the input file is non-empty):

sed's i function inserts whole lines:

With GNU sed:

# Prepends 'to be prepended' *followed by a newline*, i.e. inserts a new line.
# To prepend multiple lines, use '\n' as part of the text.
# -i.old creates a backup of the input file with extension '.old'
sed -i.old '1 i\to be prepended' inFile

A portable variant that also works with macOS / BSD sed:

# Prepends 'to be prepended' *followed by a newline*
# To prepend multiple lines, escape the ends of intermediate
# lines with '\'
sed -i.old -e '1 i\
to be prepended' inFile

Note that the literal newline after the \ is required.


If the input file must be edited in place (preserving its inode with all its attributes):

Using the venerable ed POSIX utility:

Note:

  • ed invariably reads the input file as a whole into memory first.

To prepend directly to the first line (as with sed, this won't work if the input file is completely empty (0 bytes)):

ed -s text.txt <<EOF
1 s/^/to be prepended/
w
EOF
  • -s suppressed ed's status messages.
  • Note how the commands are provided to ed as a multi-line here-document (<<EOF\n...\nEOF), i.e., via stdin; by default string expansion is performed in such documents (shell variables are interpolated); quote the opening delimiter to suppress that (e.g., <<'EOF').
  • 1 makes the 1st line the current line
  • function s performs a regex-based string substitution on the current line, as in sed; you may include literal newlines in the substitution text, but they must be \-escaped.
  • w writes the result back to the input file (for testing, replace w with ,p to only print the result, without modifying the input file).

To prepend one or more whole lines:

As with sed, the i function invariably adds a trailing newline to the text to be inserted.

ed -s text.txt <<EOF
0 i
line 1
line 2
.
w
EOF
  • 0 i makes 0 (the beginning of the file) the current line and starts insert mode (i); note that line numbers are otherwise 1-based.
  • The following lines are the text to insert before the current line, terminated with . on its own line.

Solution 7 - Unix

Prefer Adam's answer

We can make it easier to use sponge. Now we don't need to create a temporary file and rename it by

echo -e "to be prepended \n another line" | cat - text.txt | sponge text.txt

Solution 8 - Unix

Probably nothing built-in, but you could write your own pretty easily, like this:

#!/bin/bash
echo -n "$1" > /tmp/tmpfile.$$
cat "$2" >> /tmp/tmpfile.$$
mv /tmp/tmpfile.$$ "$2"

Something like that at least...

Solution 9 - Unix

Another way using sed:

sed -i.old '1 {i to be prepended
}' inFile

If the line to be prepended is multiline:

sed -i.old '1 {i\ 
to be prepended\
multiline
}' inFile

Solution 10 - Unix

Editor's note:

  • This command will result in data loss if the input file happens to be larger than your system's pipeline buffer size, which is typically 64 KB nowadays. See the comments for details.

In some circumstances prepended text may available only from stdin. Then this combination shall work.

echo "to be prepended" | cat - text.txt | tee text.txt

If you want to omit tee output, then append > /dev/null.

Solution 11 - Unix

Solution:

printf '%s\n%s' 'text to prepend' "$(cat file.txt)" > file.txt

Note that this is safe on all kind of inputs, because there are no expansions. For example, if you want to prepend !@#$%^&*()ugly text\n\t\n, it will just work:

printf '%s\n%s' '!@#$%^&*()ugly text\n\t\n' "$(cat file.txt)" > file.txt

The last part left for consideration is whitespace removal at end of file during command substitution "$(cat file.txt)". All work-arounds for this are relatively complex. If you want to preserve newlines at end of file.txt, see this: https://stackoverflow.com/a/22607352/1091436

Solution 12 - Unix

As tested in Bash (in Ubuntu), if starting with a test file via;

echo "Original Line" > test_file.txt

you can execute;

echo "$(echo "New Line"; cat test_file.txt)" > test_file.txt

or, if the version of bash is too old for $(), you can use backticks;

echo "`echo "New Line"; cat test_file.txt`" > test_file.txt

and receive the following contents of "test_file.txt";

New Line
Original Line

No intermediary file, just bash/echo.

Solution 13 - Unix

Another fairly straight forward solution is:

    $ echo -e "string\n" $(cat file)

Solution 14 - Unix

% echo blaha > blaha
% echo fizz > fizz
% cat blaha fizz > buzz
% cat buzz 
blaha
fizz

Solution 15 - Unix

If you like vi/vim, this may be more your style.

printf '0i\n%s\n.\nwq\n' prepend-text | ed file

Solution 16 - Unix

For future readers who want to append one or more lines of text (with variables or even subshell code) and keep it readable and formatted, you may enjoy this:

echo "Lonely string" > my-file.txt

Then run

cat <<EOF > my-file.txt
Hello, there!

$(cat my-file.txt)
EOF

Results of cat my-file.txt:

Hello, there!

Lonely string

This works because the read of my-file.txt happens first and in a subshell. I use this trick all the time to append important rules to config files in Docker containers rather than copy over entire config files.

Solution 17 - Unix

# create a file with content..
echo foo > /tmp/foo
# prepend a line containing "jim" to the file
sed -i "1s/^/jim\n/" /tmp/foo
# verify the content of the file has the new line prepened to it
cat /tmp/foo

Solution 18 - Unix

I'd recommend defining a function and then importing and using that where needed.

prepend_to_file() { 
    file=$1
    text=$2

    if ! [[ -f $file ]] then
        touch $file
    fi

    echo "$text" | cat - $file > $file.new

    mv -f $file.new $file
}

Then use it like so:

prepend_to_file test.txt "This is first"
prepend_to_file test.txt "This is second"

Your file contents will then be:

This is second
This is first

I'm about to use this approach for implementing a change log updater.

Solution 19 - Unix

You can do that easily with awk

cat text.txt|awk '{print "to be prepended"$0}'

It seems like the question is about prepending a string to the file not each line of the file, in this case as suggested by Tom Ekberg the following command should be used instead.

awk 'BEGIN{print "to be prepended"} {print $0}' text.txt

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionOne Two ThreeView Question on Stackoverflow
Solution 1 - UnixshimeView Answer on Stackoverflow
Solution 2 - UnixPrince John WesleyView Answer on Stackoverflow
Solution 3 - UnixSridhar SarnobatView Answer on Stackoverflow
Solution 4 - Unix0xC0000022LView Answer on Stackoverflow
Solution 5 - UnixAdamView Answer on Stackoverflow
Solution 6 - Unixmklement0View Answer on Stackoverflow
Solution 7 - UnixryanView Answer on Stackoverflow
Solution 8 - UnixRob IView Answer on Stackoverflow
Solution 9 - UnixMert NuhogluView Answer on Stackoverflow
Solution 10 - Unixsehari24jamView Answer on Stackoverflow
Solution 11 - UnixVasiliNovikovView Answer on Stackoverflow
Solution 12 - UnixAlexanderESmithView Answer on Stackoverflow
Solution 13 - UnixPatView Answer on Stackoverflow
Solution 14 - UnixNiklas RosencrantzView Answer on Stackoverflow
Solution 15 - UnixIan KellingView Answer on Stackoverflow
Solution 16 - UnixDrakesView Answer on Stackoverflow
Solution 17 - UnixJimView Answer on Stackoverflow
Solution 18 - UnixAwesomeBobX64View Answer on Stackoverflow
Solution 19 - UnixFady Mohamed OthmanView Answer on Stackoverflow