32

I want to insert text at the top of an already existing file. How can I achieve this. I tried echo and tee but was not successful.

I was trying to insert repo line at the top of sources.list file from terminal.

Note

I need an one line quick solution, because another answer's method was known to me already

ish
  • 138,666
  • 36
  • 303
  • 312
Anwar
  • 75,875
  • 31
  • 191
  • 309
  • 1
    tee adds a line at the bottom of the file e.g. `echo "deb http://extras.ubuntu.com/ubuntu precise main" | sudo tee -a /etc/apt/sources.list` -- you also need sudo before tee to get admin privileges. But why on earth would you want to add something on the very top of sources.list? – Savvas Radevic Jun 16 '12 at 11:30
  • 2
    @medigeek: somewhere in the OP's question history you'll find something about installing/updating from a CD-repo...I suspect that may be the reason... – ish Jun 16 '12 at 11:40
  • Thank @izx, Your assumption is correct. I'm quiet impressed. Can you also answer that question. That was about installing from a local repo using software-center and also setting my local repo for highest priority without placing it at the top. Thanks again. – Anwar Jun 16 '12 at 12:49
  • Can you link to the question, Anwar? I'll look into it in the next day or two. – ish Jun 16 '12 at 12:52
  • 1
    @izx, Here is the [link](http://askubuntu.com/q/135339/61218) about setting highest priority to my local repository. I will be glad if you can also check [this question about software center](http://askubuntu.com/q/137426/61218). Thanks again for your first comment. was very glad. – Anwar Jun 16 '12 at 13:48
  • I have favorited that question Anwar, so it's on my "to answer" list. – ish Jun 16 '12 at 13:53
  • 1
    @medigeek, you can see [this question](http://askubuntu.com/q/135339/61218) for the explanation of such an uncommon question. – Anwar Jun 16 '12 at 13:56
  • There is no efficient way to do that for large files: http://unix.stackexchange.com/questions/87772/add-lines-to-the-beginning-and-end-of-the-huge-file – Ciro Santilli OurBigBook.com Nov 22 '15 at 19:42
  • @CiroSantilli六四事件法轮功包卓轩 I didn't want an efficient way – Anwar Nov 23 '15 at 05:40

6 Answers6

45

It's actually quite easy with sed:

  • sed -i -e '1iHere is my new top line\' filename

  • 1i tells sed to insert the text that follows at line 1 of the file; don't forget the \ newline at the end so that the existing line 1 is moved to line 2.

ish
  • 138,666
  • 36
  • 303
  • 312
  • 1
    Thanks. Just for the note: if you want to replace, instead of inserting use `s` instead of i in `1i`. – Anwar Feb 02 '13 at 08:07
  • 4
    Sadly this fails for the empty file (it has no fist line, so sed never inserts). – Tino May 07 '14 at 01:44
  • @Tino For empty files you can just use `echo "Text Here" >> Filename` – Flotolk Aug 26 '18 at 20:17
  • doesn't work on MacOS 10 – Krishna Jul 09 '19 at 07:44
  • Just want to add that on `Ubuntu 20.04` the '\' newline gets output to the file, it is not needed (at first I had to escape the '\' in my text editor, but later removed the '\' and it seems to insert a newline fine. – CvRChameleon Jul 28 '20 at 08:09
  • With `sed 4.4` on `Ubuntu 18.04.5 LTS`, no need to add `\\` at the end – Tuna Mar 16 '21 at 13:52
8

In general editing in place with a script is tricky, but you can use echo and cat and then mv

echo "fred" > fred.txt
cat fred.txt t.txt >new.t.txt
# now the file new.t.txt has a new line "fred" at the top of it
cat new.t.txt
# can now do the rename/move
mv new.t.txt t.txt

However if you're playing with sources.list you need to add in some validation and bullet-proofing to detect errors etc because you really don't want to loose this. But that's a separate question :-)

Sean
  • 181
  • 4
6
./prepend.sh "myString" ./myfile.txt

known that prepend is my custom shell:

#!/bin/sh
#add Line at the top of File
# @author Abdennour TOUMI
if [ -e $2 ]; then
    sed -i -e '1i$1\' $2
fi

Use also a relatif path or absolute path , it should work fine :

./prepend.sh "my New Line at Top"  ../Documents/myfile.txt

Update :

if you want a permanent script for this , open nano /etc/bash.bashrc then add this function at the end of file:

function prepend(){
# @author Abdennour TOUMI
if [ -e $2 ]; then
    sed -i -e '1i$1\' $2
fi

}

Reopen you terminal and enjoy :

prepend "another line at top" /path/to/my/file.txt
Abdennour TOUMI
  • 9,137
  • 9
  • 44
  • 51
5

And why not use a genuine text editor for that? ed is the standard text editor.

ed -s filename <<< $'1i\nFIRST LINE HERE\n.\nwq'

Or, if you want the commands to be more readable:

ed -s filename < <(printf '%s\n' 1i "FIRST LINE" . wq)
  • 1: go to firstline
  • i: insert mode
  • your stuff you want to insert...
  • .: stop inserting, go back to normal mode
  • wq: write and quit, thank you, good bye.
gniourf_gniourf
  • 5,693
  • 2
  • 25
  • 28
  • How to use shell variables substitution(in the `FIRST LINE`) with this? – vp_arth Feb 02 '15 at 08:08
  • 1
    @vp_arth If your content is in variable `first_line` then: `ed -s filename < <(printf '%s\n' 1i "$first_line" . wq)`. Make sure that the variable doesn't expand to a single dot, and doesn't contain any newline characters (so sanitize it if it comes from user input). – gniourf_gniourf Feb 02 '15 at 13:25
3

You can use Vim in Ex mode:

ex -s -c '1i|hello world' -c -x sources.list
  1. 1 select 1st line

  2. i insert new line of text

  3. x save and close

Zombo
  • 1
  • 21
  • 21
2

There is always the awk option. Replace string variable with your contents. This is not an in-place change though. Personally, I tend to not make in-place changes. This is definitely a personal preference. Two things, -v signifies a variable in awk and variable n is used here to match a line number, effectively NR == 1. You could use this in any number of ways just by changing the value of n and s.

string="My New first line"; awk -v n=1 -v s="$string" 'NR == n {print s} {print}'     file.source > file.target

Example:

% cat file.source                                                                                                                                      

First Line
Second Line
Third Line

% string="Updated First Line"; awk -v n=1 -v s="$string" 'NR == n {print s} {print}' file.source > file.target; cat ./file.target                      !698

Updated First Line
First Line
Second Line
Third Line
slashdot
  • 234
  • 1
  • 2