Reputation: 9752
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
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
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
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
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
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
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
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
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