brucezepplin
brucezepplin

Reputation: 9752

add multiple lines at beginning of file

I have many files within the same subdirectory that looks like:

10 A
11 T
12 A
13 C
15 A

i.e. two columns, where the first line always begins with the number 10.

I would simply like to add lines 1-9 to the beginning of each file i.e.

1
2
3
4
5
6
7
8
9 
10 A
11 T
12 A
13 C
15 A

I don't care about appending the second column.

I know I could do

sed -i '1i1' FILE

to add a first line, but do I have to type this command out for each additional line I want to add?

Upvotes: 4

Views: 6082

Answers (8)

potong
potong

Reputation: 58351

This might work for you (GNU sed):

sed -i '1e seq 9' file1 file2 file3 ...

On the first line of each file evaluate the command seq 9.

Upvotes: 1

dawg
dawg

Reputation: 103714

You can use the Unix / POSIX / Linux cat utility to concatenate and print files.

You can use <(seq 5) as a replacement for a file to create the beginning sequence. So you can do:

$ cat <(seq 5) file
1
2
3
4
5
10 A
11 T
12 A
13 C
15 A

Then if you want the effect of editing in place, you can do:

$ cat <(seq 5) file > tmp && mv tmp file

Then:

$ cat file
1
2
3
4
5
10 A
11 T
12 A
13 C
15 A

If you don't have seq you can do:

$ cat <(echo {1..5} | tr ' ' '\n') file

instead. (Using 5 lines vs 9 in your example. Obvious how to change that...)

If you have many files, or you want to actually create the second column, you may want to create a header string:

$ header=$(for ((x=1; x<=5; x++)); do printf "%s #\n" $x; done)
$ echo "$header"
1 #
2 #
3 #
4 #
5 #

Then you can use that string instead of running seq or something:

$ cat <(echo "$header") file
1 #
2 #
3 #
4 #
5 #
10 A
11 T
12 A
13 C
15 A

Upvotes: 3

George Vasiliou
George Vasiliou

Reputation: 6335

As an alternative you might like pure bash:

$ cat file4
10 A
11 T
12 A
13 C
15 A
$ printf '%s\n%s\n' {1..9} "$(<file4)"
1
2
3
4
5
6
7
8
9
10 A
11 T
12 A
13 C
15 A

To replace the original file contents you can do it like:

printf '%s\n%s\n' {1..9} "$(<file4)" >file44 && mv -f file44 file4

Also sed -i this is what it does in the background (check sed manpages)

For multiple files you can use a loop:

for f in *;do printf '%s\n%s\n' {1..9} $(<"$f") >tmp"$f" && mv tmp"$f" "$f";done

Upvotes: 2

alvits
alvits

Reputation: 6758

This is probably the shortest one liner you can use.

sed -i -e1i{1..9} *.txt

This is equivalent to

sed -i -e1i1 -e1i2 -e1i3 -e1i4 -e1i5 -e1i6 -e1i7 -e1i8 -e1i9 *.txt

It uses bash's brace expansion.

Upvotes: 4

anubhava
anubhava

Reputation: 784898

If you have gnu awk then you can use inplace editing in awk and avoid hardcoding ending number by reading existing value from the 1st record:

awk -i inplace 'FNR==1{for (i=1; i<$1; i++) print i} 1' *.txt

Change *.txt to some other glob matching your files.

Upvotes: 6

thiagowfx
thiagowfx

Reputation: 5690

Try

seq 1 9 | cat - file.in > file.out

Where file.in is the input file you mentioned, and file.out is the name of the desired output file.

Or, even shorter (thanks @william-pursell):

{ seq 1 9; cat file.in; } > file.out

Upvotes: 8

ephemient
ephemient

Reputation: 204668

sed -i -e '1!b;'"$(printf 'i%d\n' {1..9})"

This is equivalent to running

sed -i -e '1!b;i1
i2
i3
i4
i5
i6
i7
i8
i9
'

but easier to write. The 1!b skips the rest of the commands on lines other than the first, but you could also use a 1 address instead.

sed -i -e "$(printf '1i%d\n' {1..9})"

Upvotes: 2

Barmar
Barmar

Reputation: 780688

You can insert multiple lines with sed by putting backslash after the i command.

sed -i '1i\
1\
2\
3\
4\
5\
6\
7\
8\
9\
' file

Upvotes: 2

Related Questions