0

The specific task is to use the header of a KML file and insert it into hundreds of split up KML data files that do not have the header.

The KML header is multiple lines and specific spacing. I've found I can use Sed with the 'r' readfile option to grab the contents of a file containing the header. However when I insert the data with '1r' the header is placed in the file starting on the second line. sed doesn't seem to let me address 'line 0' to insert before. Insert mode would work, but I wouldn't be able to just grab the header format that is saved in a file and would need to script the entire header.

#!/bin/bash
for i in ./Split/*;
        do sed -i '1r KML_Header.txt' $i
done

The KML Header Looks like this:

<?xml version='1.0' encoding='UTF-8'?>
<kml xmlns='http://www.opengis.net/kml/2.2'xmlns:gx='http://www.google.com/kml/ext/2.2'>
    <Document>
        <Placemark>
            <open>1</open>
            <gx:Track>
                 <altitudeMode>clampToGround</altitudeMode>

The end result with the header will look something like this:

<?xml version='1.0' encoding='UTF-8'?>
<kml xmlns='http://www.opengis.net/kml/2.2'xmlns:gx='http://www.google.com/kml/ext/2.2'>
    <Document>
        <Placemark>
            <open>1</open>
            <gx:Track>
                 <altitudeMode>clampToGround</altitudeMode>
            <when>2017-11-16T11:47:52Z</when>
            <gx:coord>-97.8216659 30.481537499999998 261</gx:coord>
            <when>2017-11-16T11:47:44Z</when>
            <gx:coord>-97.8216137 30.481513600000003 259</gx:coord>
            <when>2017-11-16T11:45:37Z</when>
            <gx:coord>-97.8216659 30.481537499999998 261</gx:coord>
            <when>2017-11-16T11:44:54Z</when>
            <gx:coord>-97.82162970000002 30.481479699999998 261</gx:coord>
            <when>2017-11-16T11:39:55Z</when>

However, this is what my current best command gets me:

<when>2017-11-16T11:47:52Z</when>
<?xml version='1.0' encoding='UTF-8'?>
<kml xmlns='http://www.opengis.net/kml/2.2'xmlns:gx='http://www.google.com/kml/ext/2.2'>
    <Document>
        <Placemark>
            <open>1</open>
            <gx:Track>
                 <altitudeMode>clampToGround</altitudeMode>
            <gx:coord>-97.8216659 30.481537499999998 261</gx:coord>
            <when>2017-11-16T11:47:44Z</when>
            <gx:coord>-97.8216137 30.481513600000003 259</gx:coord>
            <when>2017-11-16T11:45:37Z</when>
            <gx:coord>-97.8216659 30.481537499999998 261</gx:coord>
            <when>2017-11-16T11:44:54Z</when>
            <gx:coord>-97.82162970000002 30.481479699999998 261</gx:coord>
            <when>2017-11-16T11:39:55Z</when>
brock.bell
  • 13
  • 3
  • There are numerous ways to do this, for example here: https://superuser.com/questions/246837/how-do-i-add-text-to-the-beginning-of-a-file-in-bash or https://stackoverflow.com/questions/9533679/how-to-insert-a-text-at-the-beginning-of-a-file – thanasisp Nov 17 '17 at 23:48

2 Answers2

1

I suggest trying awk. With GNU awk:

awk -i inplace 'FNR==NR{hdr=hdr "\n" $0; next} FNR==1{print substr(hdr,2)} 1' inplace=0 header inplace=1 ./Split/*

How it works:

  • -i inplace

    This tells awk to change files in-place.

  • FNR==NR{hdr=hdr "\n" $0; next}

    This tells awk that, when reading the first file (header), it should save the contents in the variable hdr, skip the rest of the commands, and jump to the next line.

  • FNR==1{print substr(hdr,2)}

    This tells that, when it starts a new file, it should first print the header (minus the unneeded initial newline in variable hdr).

  • 1

    This is awks cryptic shorthand for print-the-current-line.

Example

$ cat >header
1  
2
3
$ cat >file1
4
5
6
$ cat >file2
44
55
66

Using our command to change the files in-place:

$ awk -i inplace 'FNR==NR{hdr=hdr "\n" $0; next} FNR==1{print substr(hdr,2)} 1' inplace=0 header inplace=1 file*
$ cat file1
1
2
3
4
5
6
$ cat file2
1
2
3
44
55
66

Hat tip to Barmar.

John1024
  • 97,609
  • 11
  • 105
  • 133
  • 1
    There's a better way that doesn't require rewriting the header file. Put `inplace=0` before `header` and `inplace=1` after it. – Barmar Nov 18 '17 at 00:00
  • 1
    See https://www.gnu.org/software/gawk/manual/html_node/Extension-Sample-Inplace.html for the details of how inplace works in GNU awk. – Barmar Nov 18 '17 at 00:01
  • @Barmar Still better. Thanks! – John1024 Nov 18 '17 at 00:12
  • Thanks @John1024 I was able to get this one to work. I really appreciate the detailed explanation of the segments, too. I'm always interested in learning the seemingly endless options of awk and sed. I do prefer the more simple approach from Barmar though. – brock.bell Nov 20 '17 at 15:30
1

You can use cat file1 file2 > newfile to prepend file1 to file2. Do this in a loop.

for i in Split/*
do
    cat KML_Header.txt "$i" > "$i.new" && mv "$i.new" "$i"
done
Barmar
  • 596,455
  • 48
  • 393
  • 495