156

I've been looking around sed command to add text into a file in a specific line. This works adding text after line 1:

sed '1 a\

But I want to add it before line 1. It would be:

sed '0 a\

but I get this error: invalid usage of line address 0.

Any suggestion?

αғsнιη
  • 40,939
  • 15
  • 71
  • 114
Manolo
  • 1,697
  • 2
  • 11
  • 11

16 Answers16

212

Use sed's insert (i) option which will insert the text in the preceding line.

sed '1 i\

Question author's update:

To make it edit the file in place - with GNU sed - I had to add the -i option:

sed -i '1 i\anything' file

Also syntax

sed  -i '1i text' filename

For non-GNU sed

You need to hit the return key immediately after the backslash 1i\ and after first_line_text:

sed -i '1i\
first_line_text
'

Also note that some non-GNU sed implementations (for example the one on macOS) require an argument for the -i flag (use -i '' to get the same effect as with GNU sed).

For sed implementations that does not support -i at all, run without this option but redirect the output to a new file. Then replace the old file with the newly created file.

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
suspectus
  • 5,890
  • 4
  • 20
  • 26
  • 1
    It doesn't work without `-i` option. I'll update your answer before accepting. – Manolo Nov 08 '13 at 12:07
  • 1
    thanks. What OS are you using? Original solution worked on OpenSuse 9. – suspectus Nov 08 '13 at 12:22
  • Linux Mint 13 Maya – Manolo Nov 08 '13 at 12:25
  • 1
    Interesting! I'm on Lubuntu 13.10 and `sed '1 i\this text is entered above the existing first line' file` works for me. –  Nov 08 '13 at 13:47
  • 2
    Here, using `sed (GNU sed) 4.2.2` just `sed '1 i text to insert' -i file` worked like a charm. Thanks – ton Feb 15 '16 at 14:06
  • can confirm, gnu sed does not require the `-i` flag – Yoshua Wuyts Mar 02 '16 at 00:11
  • 5
    Does not work on empty files. – rudimeier Sep 28 '16 at 20:32
  • 1
    The `-i` argument to `sed` tells it to edit the file in-place — I have a feeling all of the commenters here were seeing the same behavior, but simply had different expectations. Without `-i`, sed will execute the commands specified and _output_ the results to the terminal, unless you redirect it somewhere else. WITH `-i`, it will actually modify the file on disk, and write the changed version in place of the original. Two different approaches to `sed`-ing a file's contents, depending whether you need to preserve the unaltered version of the input file. – FeRD Mar 03 '18 at 23:27
  • 1
    @rudimeier Huh! You're right, it doesn't work on _completely_ empty files. I guess because sed is super-literal, and you can't insert text at line 1 when there _isn't_ a "line 1" in the file. So `touch empty.txt && sed '1i Text' -i empty.txt` will do nothing, whereas `echo > blank.txt && sed '1i Text' -i blank.txt` will result in `blank.txt` containing a line that reads "Text", with a blank line after it. – FeRD Mar 03 '18 at 23:41
  • 1
    @FeRD See my bad ranked `awk` answer below. This should work. – rudimeier Mar 04 '18 at 00:02
  • Well, inserting text into a completely empty file is kind of a pathological case, anyway. I can see how some script might need to be able to handle that case, but in any interactive use the way to "insert" text at the start of an empty file is just `echo "text" > file`. :-) – FeRD Mar 04 '18 at 00:05
  • I get "invalid command code f" with osx – Johny19 Apr 12 '18 at 09:45
  • Just added an update for OSX – suspectus Apr 15 '18 at 20:06
  • How do you insert a string which needs to be processed first? – Timothy Swan Apr 18 '18 at 21:40
  • 1
    For macOS if you declare double quotes for some reason then you should declare \\ just before the new-line or text. for example: `sed -i '' "1i\\ "` – emrcftci Jan 04 '22 at 15:21
  • not sure what this command do, i just got `sed: 1: "~/testing.txt": extra characters at the end of q command`, definitely not a solution for the post title – CuriousNewbie Apr 07 '22 at 05:36
  • For MacOS sed: `-e $'1i\\\ntext to add'` – Rob Aug 11 '22 at 20:50
  • how toadd variable value in sed command – rose Nov 15 '22 at 05:08
43

Echo is used to get the text. Cat filename - prints the file in the console and > uses it to send to another file filename1 and then we move filename1 to filename to get the text inserted to the first line of desired file.

  (echo "some text" && cat filename) > filename1 && mv filename1 filename
Ankit Shah
  • 594
  • 4
  • 7
  • 11
    Please let me know why the following is downvoted – Ankit Shah Jan 09 '17 at 14:58
  • 1
    Perhaps because the OP mentions sed. That does not deserve a down vote in my opinion. That solution was even the best fitting my needs, then upvoted. – рüффп Apr 12 '18 at 10:46
  • 1
    I upvoted. works on ksh for me. – arcee123 Aug 22 '19 at 13:47
  • 3
    this is great solutions! it work in Makefile & MacOS well. – zx1986 Jun 18 '20 at 23:33
  • 1
    1. Sed is installed _everywhere_ 2. This is not an elegant solution : You call 1 builtin + cat + mv instead of just calling one command. Imagine the waste of time if this solution is used as part of a script that will run it thousands of time. – binarym Jun 10 '22 at 09:09
  • 1
    @binarym as what I know, `sed` is not globally working in sync *everywhere*, for example : some of `sed` command are not do-able in OSX, even tho the program name is called `sed`, some say installing `gnu-sed` will fix the problem, but that mean not using the tool that comes with the OS anymore, instead, using outsourcing tool, but again, the post creator asking for sed, that's probably the main reason this answer in not accepted as solution. – CuriousNewbie Nov 11 '22 at 01:05
23

You can use the POSIX tool ex:

ex a.txt <<eof
1 insert
Sunday
.
xit
eof

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html

Zombo
  • 1
  • 5
  • 43
  • 62
13

Using GNU awk >= 4.1:

awk -i inplace 'BEGINFILE{print "first line"}{print}' foo.sh

In opposite to all the sed answers, this works on empty files too.

GAD3R
  • 63,407
  • 31
  • 131
  • 192
rudimeier
  • 9,967
  • 2
  • 33
  • 45
  • 1
    `inplace` is a library, and unfortunately it appears on all awk distributions ship it. I get "awk: fatal: can't open source file 'inplace' for reading" `GNU Awk 4.2.1, API: 2.0 (GNU MPFR 4.0.1, GNU MP 6.1.2)` – vossad01 Jul 08 '18 at 14:15
9
sed  -i '1i new_text' file_name

If you don't specify the -i option, it won't show any error, and displays the output on standard terminal, but doesn't insert the text in the file.

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
devi.
  • 89
  • 1
  • 1
  • The question is not about the `-i` switch. – don_crissti Mar 14 '16 at 20:30
  • How do you figure that?  It ***is*** an answer to the question.  Yes, it's *similar* to the accepted answer, but not exactly the same. – G-Man Says 'Reinstate Monica' Mar 14 '16 at 22:51
  • @G-Man - one might argue the template used by cas is far from ideal but really, this is _similar_ like in _nearly identical_... the difference being the spacing and the fact this one has no backslash. As far as I am concerned they are technically identical (as they are both `gnu sed` specific and it just happens that `gnu sed` will accept the `i` without a backslash). If others think this warrants a separate answer + an upvote... oh well. – don_crissti Mar 15 '16 at 00:41
7

You want to insert text before the first line rather than append it after, so use

sed '1 i\
your_text' your_file

A here document can also help:

cat /dev/stdin your_file <<EOI
Your text
goes here
EOI
Joseph R.
  • 38,849
  • 7
  • 107
  • 143
5

The 0a command you attempted does work in ex, the predecessor to vi:

printf '%s\n' 0a 'Anything you want to add' . x | ex file.txt

The printf command by itself outputs:

0a
Anything you want to add
.
x

The 0a means append after the 0th line (i.e. before the first line).

The next line or multiple lines is literal text to be added.

The . on a line by itself terminates the "append" command.

The x causes Ex to save the changes to the file and exit.

Wildcard
  • 35,316
  • 26
  • 130
  • 258
3

I am surprised that in this old question nobody has shown the most common (and quite simple in this case) sed command:

$ sed  -i '1s/^/new_text\
/' file_name

Which works in most shells and is portable to several sed versions, provided that the file contains at least one valid line.
If GNU sed is available, you may use this:

$ sed -i '1s/^/new_text\n' file_name

The difference is that GNU sed allow the use of a \n for a newline and others need a literal newline preceded by a backslash (which also work in GNU sed anyway).

If a shell which accepts the $'…' syntax is in use, you may insert the newline directly, so sed sees that the newline is already there:

$ sed -i $'1s/^/new_text\\\n/' file_name

Which works for more sed versions.

If the file has no lines (i.e: its empty) just:

$ echo "new_text" > file_name
  • What if there is no lines in the file? – Just a learner Jan 09 '20 at 07:21
  • @Justalearner The title of the question asks for: *insert text before the first line of a file*, so, a first line must already exist. That is also a problem for the selected answer. –  Jan 13 '20 at 19:04
  • Amazing answer @Isaac. This is certainly the only solution which works in the literal sense. I needed to add "schema": before the first line without any new line to be added. Your solution work -> sed -i '1s/^/"schema":/' o – nitinr708 Apr 01 '20 at 19:13
2

I had issues with BSD sed (MacOS) and inserting text from a variable, so this is how I did it:

headers=a,b,c
sed -i '' -e "1{x;s/^.*/$headers/p;x;} some_file"

Explanation

  • 1{...} This affects only the first line
  • x swap the current line with the hold space (currently empty)
  • s/../../p replaces (the now empty line) with the expected text (this avoids the line-break problem) and outputs it (so the first line will be get printed)
  • x swap again, retrieving the file first line which was in the hold space into the pattern space
estani
  • 863
  • 7
  • 9
1

Unfortunately, all the answers above (mostly with sed) didn't work out for me since they all substituted the first line. I am on an Ubuntu 16.04 LTS machine. Here is my workaround with GNU Awk 4.0.2:

awk '{if(NR==1){$0="NEW_FIRST_LINE"$0; print $0} ;if(NR!=1){print $0}}' file_name
  • 2
    Not sure what you're talking about... There's only one `sed` answer that uses replacement but it doesn't substitute the existing line. – don_crissti Nov 15 '18 at 18:06
1

Adding the text hello before the first line without a carriage return or line feed to the file myfile

sed -i '1s/^/hello /' myfile

This will also not output the entire file on the terminal.

Paulo Tomé
  • 3,754
  • 6
  • 26
  • 38
FastGTR
  • 111
  • 2
1

To insert text to the first line and put the rest on a new line using sed on macOS this worked for me

sed -i '' '1 i \
Insert
' ~/Downloads/File-path.txt
Ax_
  • 121
  • 6
1
echo -e "task goes here\n$(cat todo.txt)" > todo.txt

echo "task goes here
$(cat todo.txt)" > todo.txt

echo 'task goes here'$'\n'"$(cat todo.txt)" > todo.txt

(https://superuser.com/questions/246837/how-do-i-add-text-to-the-beginning-of-a-file-in-bash)

0

If anyone is interested, my problem was to insert same header line into several files. Thanks to proposed solution, I came up with this :

sed -i 1i\ $(cat header_line) data.csv

where header_line is a file containing desired first line ,

roaima
  • 107,089
  • 14
  • 139
  • 261
rookie
  • 1
0

Just similar to Ankit Shah's answer:

(echo "some text" && cat filename) > /tmp/filename && cat /tmp/filename > filename

It's not convenient to use such a long command, so I create a simple bash function (in .bashrc or elsewhere possible) as following:

echo0 () {
  (echo ${@:2} && cat $1) > /tmp/$1
  cat /tmp/$1 > $1
}
# $1 is your-file-name, ${@:2} are contents after "your-file-name".
# How to use:
#   > echo0 myfile hellow world etc.
#   > head myfile
#     hellow world etc.
#     ...
Hao Liu
  • 1
  • 1
-2

sed can insert (multiple times) before the first and after the last

I would assume that anyone who searched for how to insert/append text to the beginning/end of a file probably also needs to know how to do the other also.

cal |                            \
  gsed -E                        \
       -e     '1i\{'             \
       -e     '1i\  "lines": ['  \
       -e 's/(.*)/    "\1",/'    \
       -e '$s/,$//'              \
       -e     '$a\  ]'           \
       -e     '$a\}'

Explanation

This is cal output piped to gnu-sed (called gsed on macOS installed via brew.sh) with extended RegEx (-E) and 6 "scripts" applied (-e) and line breaks escaped with \ for readability.

  • Scripts 1 & 2 use 1i\ to "at line 1, insert".
  • Scripts 5 & 6 use $a\ to "at line <last>, append".
    • I vertically aligned the text outputs to make the code represent what is expected in the result.
  • Scripts 3 & 4 do substitutions
    • Script 4 applies only to "line <last>" because of the $ placed before the s/.

The result is converting command output to valid JSON.

output

{
  "lines": [
    "    October 2019      ",
    "Su Mo Tu We Th Fr Sa  ",
    "       1  2  3  4  5  ",
    " 6  7  8  9 10 11 12  ",
    "13 14 15 16 17 18 19  ",
    "20 21 22 23 24 25 26  ",
    "27 28 29 30 31        ",
    "                      "
  ]
}
Bruno Bronosky
  • 4,434
  • 2
  • 27
  • 24
  • While I haven't voted on your question, note that we already have several answers, including an accepted one, that demonstrate the desired result. – Jeff Schaller Oct 22 '19 at 12:12
  • @JeffSchaller The Stack Exchange community is not a forum. Its purpose extends beyond helping the OP get unblocked. The goal is to seed the global knowledge base with many options that seekers can stumble upon when searching for answers. The reason I titled my answer is to help users recognize the utility of this answer before they even click the Google result. – Bruno Bronosky Oct 22 '19 at 16:09
  • 3
    What I'm saying is that your answer isn't providing any *new* options (answers) for future readers of this question. We already have four answers that use variations of `1i` to insert text before the first line. Someone with this question would have to extract the parts they need from your answer in order to solve their problem. Questions are free, so I'd invite you to ask & answer your own question in order to provide your specific answer. – Jeff Schaller Oct 22 '19 at 16:19