How to split a GPX track file into several files of N trackpoints each?

Surprisingly it seems gpsbabel indeed can't do it. But at least it can help by first converting to csv. Then I split the result with Unix' split and convert back to gpx with gpsbabel. A similar strategy might work with PowerShell, but I don't know if it has a split equivalent. Here is the bash function I used:

splitTrack() {
  # $1 shall be the gpx file to split
  pfx="${1%.*}-"
  gpsbabel -i gpx -f "$1" -t -o csv -F - \
  | split -d -l 500 --additional-suffix=.csv - "$pfx"

  for f in "$pfx"*.csv; do
    fout=${f%.*}.gpx
    gpsbabel -i csv -f "$f" -x transform,trk=wpt -x nuketypes,waypoints \
             -o gpx -F "$fout"
    rm "$f"
  done
}

EDIT: Added hint from comments about getting track points out instead of way points.


Thanks for the script! It's useful to me as well because my Garmin bike navigator starts to throw trackpoints away after a certain number of trackpoints is reached.

I added a separation of waypoints and tracks and a little bit of "compression" to Harald's script (which works in zsh as well).

splitTrack() {
  # $1 shall be the gpx file to split
  pfx="${1%.*}-"
  # Split tracks off and simplify track (reduce number of trackpoints but keep 
  # sufficient accuracy for bike navigation)
  gpsbabel -i gpx -f "$1" -x nuketypes,waypoints,routes \
  -x simplify,crosstrack,error=0.003k -o gpx -F "${pfx}tracks.gpx"
  # Split waypoints off (import as extra POI gpx to device)
  gpsbabel -i gpx -f "$1" -x nuketypes,tracks,routes -o gpx \
  -F "${pfx}waypoints.gpx"
  # 500 pack from tracks in CSV, start suffix with 01 instead of 00
  gpsbabel -i gpx -f "${pfx}tracks.gpx" -t -o csv -F - \
  | split -d --numeric=1 -l 500 --additional-suffix=.csv - "$pfx"
  rm "${pfx}tracks.gpx"
  # CSV back to gpx
  for f in "$pfx"*.csv; do
    fout=${f%.*}.gpx
    gpsbabel -i csv -f "$f" -x transform,trk=wpt -x nuketypes,waypoints \
         -o gpx -F "$fout"
    rm "$f"
  done
}

If you want to keep elevation data as well, you may want to use the UNICSV format. Please adjust the re-import command to the field set exported from the GPX to (Uni)CSV. For more information see https://www.gpsbabel.org/htmldoc-development/fmt_unicsv.html. The following snippet requires the usual GNU toolset (sed/tail/split) installed.

splitTrack() {
    # ===
    # abort if no file is passed as argument 1

    if ! [[ -f "$1" ]] 
        then
            echo File missing!
            return
    fi
    # ===

    # ===
    # Set prefix for files according to source file name

    pfx="${1%.*}-"
    # ===

    # ===
    # save waypoints in another file

    gpsbabel \
        -i gpx \
        -f "$1" \
        -x nuketypes,tracks,routes \
        -o gpx \
        -F "${pfx}waypoints.gpx"
    # ===

    # ===
    # filter only track
    # simplify track
    # transform simplified track into waypoints
    # print waypoints in UNICSV format
    # pipe
    # ignore UNICSV header
    # pipe
    # take 500 lines and duplicate each 500th line (overlap 1 line)
    # in order to avoid gap in transition from one to next track part
    # credit goes to https://stackoverflow.com/questions/21756040/extract-a-range-of-rows-with-overlap-using-sed/21757062#21757062
    # pipe
    # split/save each block of 500 lines into separated UNICSV files with prefix according to source file

    gpsbabel \
        -i gpx \
        -f "$1" \
        -x nuketypes,waypoints,routes \
        -x simplify,crosstrack,error=0.003k \
        -x transform,wpt=trk \
        -o unicsv \
        -F - \
    | tail \
        -n +2 \
    | sed \
        -nr ':a;$!{N;s/[^\n]+/&/500;Ta};p;$q;s/.*((\n[^\n]*){1})$/\1/;D' \
    | split \
        -d \
        -a 3 \
        --numeric=1 \
        -l 500 \
        --additional-suffix=.csv \
        - \
        "$pfx"
    # ===

    # ===
    # convert separated UNICSV files back to GPX track files 
    # by transforming UNICSV waypoints back to trackpoints
    # also filter out superfluous name tag

    for f in "$pfx"*.csv; do
        gpsbabel \
            -i unicsv,fields=no+lat+lon+name+ele \
            -f "$f" \
            -x transform,trk=wpt \
            -x nuketypes,waypoints \
            -o gpx \
            -F - \
        | grep \
            -v '<name>.*</name>\|<cmt>.*</cmt>\|<desc>.*</desc>' \
            > "${f%.*}.gpx"
        rm "$f"
    done
    # ===

    return
}

This should work for example with the GPX tracks generated by https://brouter.de/brouter-web

Tags:

Gpx