Recently, I had to upload a backup of my tasks and events to my CalDAV/CardDAV Server. The backup was one VCALENDAR containing all the events (VEVENT) and tasks (VTODO). However, the event and todo items are stored on the server individually and, moreover, the calendar server does not support the upload of a VCALENDAR containing multiple entries.
To solve this I wrote a quick Python script which splits a VCALENDAR containing multiple VEVENTs/VTODOs into multiple VCALENDARs containing only a single event or task.; (I’m sure this can be done in a one-line awk script as well)
"""Splits a VCALENDAR file (a collection of VEVENT and VTODO objects) in its parts, i.e., individual files containing a single VEVENT/VTODO.The files are named based on the UID of the VEVENT/VTODO object and each VEVENT/VTODO is wrapped in the same VCALENDAR meta data as the original file."""PREFIX="out/"defextractUID(vitem):""" Extracts the UID attribute fron VEVENT/VTODO """forxinvitem:ifx[0:3]=="UID":returnx.split(":")defwriteToFile(entry,pre,post):uid=extractUID(entry)# File name is UID of event. strip the two newline charactersoutput=open(PREFIX+uid[:-2]+'.ics','w')output.write(''.join(pre))output.write(''.join(entry))output.write(''.join(post))output.close()defmain():# open VCALENDAR file vcal=open('backup.ics','r').readlines()# Preamblepre=# Postamblepost=# current entryentry=# list of all VEVENTS/VTODOsvitems=forlineinvcal:# Relevant blocks start with "BEGIN:VEVENT" OR "BEGIN:VTODO"ifline.startswith("BEGIN:VEVENT")or \
line.startswith("BEGIN:VTODO"):# everything before the first VEVENT/VTODO was preambleifnotpre:pre=entryentry=entry.append(line)# When block is complete, store to list of vitems and start new entryifline.startswith("END:VEVENT")or \
line.startswith("END:VTODO"):# Add item to list of vitemsvitems.append(entry)entry=# everything after the last entry is postamblepost=entry# output all events and todosforxinvitems:writeToFile(x,pre,post)if__name__=="__main__":main()
The resulting files can easily be uploaded to your caldav server using, e.g., the following curl command: