Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Schubi

macrumors newbie
Original poster
Mar 22, 2013
19
0
Hello,

I wonder if anyone can help with AppleScript and knows the latest OSX Calendar functions well.

My goal is to backup each calendar within the Calendar application to a single directory as .ics files.

I've been reading through this post from 2007 and tried to modify the script from xUKHCx without any success. I assume that the Calendar application has changed quite a bit over the last 5 years.

Code:
-- Set paths and variables ------------------------------------------------------------------------------------
set timeStamp to do shell script "date \"+%Y%m%d\""
set calendar_folder to POSIX path of (path to home folder from user domain)
set sources_folder to quoted form of (calendar_folder & "Library/Calendars")
set backup_folder to POSIX path of ("Users/ros/Backup/Calendar/")

-- Find all Info.plist files ---------------------------------------------------------------------------------
set infolist to paragraphs of (do shell script "find -f " & sources_folder & "| grep -v “/Contents” | grep Info.plist$")
set calstartlist to {}
set caldestlist to {}
set calnamelist to {}

-- Create a backup folder -------------------------------------------------------------------------------------
try
	set destfolder to backup_folder
	set fileName to timeStamp
	do shell script "mkdir -p " & quoted form of destfolder & "/" & quoted form of fileName
	set destFile to destDir & "/" & fileName
end try

-- Search through above results -------------------------------------------------------------------------------
repeat with calname in infolist
	set calname to calname as string
	set calname to text 1 thru -7 of calname

-- Create a path to the original .ics files -------------------------------------------------------------------
	set calstart to quoted form of (text 1 thru -5 of calname & "corestorage.ics")
	copy calname to end of calstartlist
	set calname to quoted form of calname
	
-- Read the Info.plist and grab the calendar names ------------------------------------------------------------
	try
		set calname to (do shell script "defaults read " & calname & " Title")
		set caldest to quoted form of (backup_folder & calname & ".ics")
		copy calname to end of calnamelist
		copy caldest to end of caldestlist
	end try
end repeat

set calexport to choose from list calnamelist with multiple selections allowed
repeat with calname in infolist
	set calname to calname as string
	set calname to text 1 thru -7 of calname
	set calstart to quoted form of (text 1 thru -5 of calname & "corestorage.ics")
	copy calname to end of calstartlist
	set calname to quoted form of calname
	try
		set calname to (do shell script "defaults read " & calname & " Title")
		set caldest to quoted form of (backup_folder & calname & ".ics")
		if calname is in calexport then
			do shell script "ditto " & calstart & " " & caldest
		end if
	end try
end repeat

The end result should be as in the attached screenshot. Any help is greatly appreciated - after 2 days of searching through Google and other forums.. I'm out of skills and ideas!
 

Attachments

  • Screen Shot 2013-03-23 at 0.29.55 .png
    Screen Shot 2013-03-23 at 0.29.55 .png
    147.8 KB · Views: 352

kryten2

macrumors 65816
Mar 17, 2012
1,114
99
Belgium
My goal is to backup each calendar within the Calendar application to a single directory as .ics files.
I couldn't find corestorage.ics on my mac or anything about exporting calendars in iCal's dictionary so I decided to go with GUI scripting. Not the best or most elegant solution but I think it does the job.

Code:
property savePath : ""
set timeStamp to do shell script "date \"+%Y%m%d\""
set backup_folder to "/Users/kryten/Backup/Calendar/"
set macPath_Backup_folder to POSIX file backup_folder
try
	tell application "Finder"
		if not (exists macPath_Backup_folder) then
			set macBackup_folderExists to false
			my createDirectories(backup_folder, timeStamp)
		else
			set savePath to backup_folder & timeStamp
			--log savePath
			set macBackup_folderExists to true
		end if
	end tell
end try

on createDirectories(theFolders, theDate)
	set savePath to do shell script "mkdir -vp " & quoted form of theFolders & quoted form of theDate
	--log savePath
end createDirectories

tell application "iCal"
	activate
	delay 2
	set everyCalendar to every calendar
	set countLoop to 0
	repeat with aCalendar in everyCalendar
		set calendarName to name of aCalendar
		set countLoop to countLoop + 1
		--log countLoop
		tell application "System Events"
			tell application process "iCal"
				click menu item "Export…" of menu 1 of menu item "Export…" of menu 1 of menu bar item "File" of menu bar 1
				delay 0.5
				--keystroke aCalendar's name
				keystroke calendarName
				delay 0.2
				if countLoop = 1 then
					keystroke "g" using {command down, shift down}
					delay 0.2
					if macBackup_folderExists is false then
						keystroke third paragraph of savePath
					else
						keystroke savePath
					end if
					--delay 0.5
					keystroke return
					--delay 0.5
				end if
				keystroke return
			end tell
		end tell
	end repeat
end tell

Note : Make sure Enable access for assistive devices is checked in Universal Access of System Preferences. Tested on Snow Leopard with iCal 4.0.4. YMMV.
 

Attachments

  • Screen shot 2013-03-23 at 01.25.20.png
    Screen shot 2013-03-23 at 01.25.20.png
    87.5 KB · Views: 222
  • Screen shot 2013-03-23 at 01.25.27.png
    Screen shot 2013-03-23 at 01.25.27.png
    103.6 KB · Views: 208

Schubi

macrumors newbie
Original poster
Mar 22, 2013
19
0
Hello kryten2,

Thanks for looking into this. The script is what I've been looking for - apart for some small problems.

1) It does not create a new backup folder ('YYYYMMDD').

2) The script runs through the actions very quickly and stumbles upon an event creating a calendar backup called Employmentnment.ics instead of Employment.ics

3) All backup files have the same file size. Clicking a manual 'File -> Export -> Export...' in Calendar however saves the calendars with their correct file size.

4) The Calendar menu has slightly changed in Calendar 6.0 (1648) so I made the following adjustments to 'click menu item'. Here's the whole script:
Code:
property savePath : ""
set timeStamp to do shell script "date \"+%Y%m%d\""
set backup_folder to "/Users/ros/Backup/Calendar/"
set macPath_Backup_folder to POSIX file backup_folder
try
	tell application "Finder"
		if not (exists macPath_Backup_folder) then
			set macBackup_folderExists to false
			my createDirectories(backup_folder, timeStamp)
		else
			set savePath to backup_folder & timeStamp
			--log savePath
			set macBackup_folderExists to true
		end if
	end tell
end try

on createDirectories(theFolders, theDate)
	set savePath to do shell script "mkdir -vp " & quoted form of theFolders & quoted form of theDate
	--log savePath
end createDirectories

tell application "Calendar"
	activate
	delay 2
	set everyCalendar to every calendar
	set countLoop to 0
	repeat with aCalendar in everyCalendar
		set calendarName to name of aCalendar
		set countLoop to countLoop + 1
		--log countLoop
		tell application "System Events"
			tell application process "Calendar"
				click menu item "Export…" of menu 1 of menu item "Export" of menu 1 of menu bar item "File" of menu bar 1
				delay 0.5
				--keystroke aCalendar's name
				keystroke calendarName
				delay 0.2
				if countLoop = 1 then
					keystroke "g" using {command down, shift down}
					delay 0.2
					if macBackup_folderExists is false then
						keystroke third paragraph of savePath
					else
						keystroke savePath
					end if
					--delay 0.5
					keystroke return
					--delay 0.5
				end if
				keystroke return
			end tell
		end tell
	end repeat
end tell


I've created a screencast that shows what the script does (31MB, .mov): http://195.30.252.25/files/dmp/ScreencastCalendar.mov
 
Last edited:

kryten2

macrumors 65816
Mar 17, 2012
1,114
99
Belgium
Hello kryten2,

Thanks for looking into this. The script is what I've been looking for - apart for some small problems.

1) It does not create a new backup folder ('YYYYMMDD').

2) The script runs through the actions very quickly and stumbles upon an event creating a calendar backup called Employmentnment.ics instead of Employment.ics

3) All backup files have the same file size. Clicking a manual 'File -> Export -> Export...' in Calendar however saves the calendars with their correct file size.

4) The Calendar menu has slightly changed in Calendar 6.0 (1648) so I made the following adjustments to 'click menu item'. Here's the whole script:

I've created a screencast that shows what the script does (31MB, .mov): http://195.30.252.25/files/dmp/ScreencastCalendar.mov

About 5 minutes after posting my reply and thinking about it a little bit harder I knew this script was no good.

1) Make a new script with everything except the tell application iCal block and look at the replies and events in Applescript Editor why it fails to create a new backup folder. Uncomment the log statements for more feedback.

2) Yeah it runs fast on your system. Increase the delays.

3) Here's the real problem. The script loops through every calendar but doesn't really export the right calendars. Mainly because iCal doesn't understand( on Leopard and Snow Leopard anyway) the selection keyword.
I'll look into UI browser to select them with GUI scripting. Unfortunately I'm not on Mountain Lion so I can't really test anything.

I'll see if I can make some time to get ML running on my hack to come up with a satisfying solution to your problem. There's on thing you can do. Can you look into the following path if you see a corestorage.ics file?

/Users/ros/Library/Application Support/iCal/Sources/2B835489-C867-4DBB-9AFC-5986AA3F58F4.calendar/

The id part is just an example and should be different on your mac. If it's there and also the info.plist file the first script uses it should be possible to make the first script you posted work after you change the sources_folder to the right path eg /Users/ros/Library/Application Support/iCal
 

Schubi

macrumors newbie
Original poster
Mar 22, 2013
19
0
Thanks for the effort you are putting into helping me!

Make a new script with everything except the tell application iCal block and look at the replies and events in Applescript Editor why it fails to create a new backup folder. Uncomment the log statements for more feedback.

Modified script running with logging activated:
Code:
property savePath : ""
set timeStamp to do shell script "date \"+%Y%m%d\""
set backup_folder to "/Users/ros/Backup/Calendar/"
set macPath_Backup_folder to POSIX file backup_folder
try
	tell application "Finder"
		if not (exists macPath_Backup_folder) then
			set macBackup_folderExists to false
			my createDirectories(backup_folder, timeStamp)
		else
			set savePath to backup_folder & timeStamp
			log savePath
			set macBackup_folderExists to true
		end if
	end tell
end try

on createDirectories(theFolders, theDate)
	set savePath to do shell script "mkdir -vp " & quoted form of theFolders & quoted form of theDate
	log savePath
end createDirectories

From the Events/Replies section in AppleScript Editor (although the folder '20130324' does NOT exist in /Users/ros/Backup/Calendar/):
Code:
tell current application
	do shell script "date \"+%Y%m%d\""
		--> "20130324"
end tell
tell application "Finder"
	exists file "Main:Users:ros:Backup:Calendar:"
		--> true
	(*/Users/ros/Backup/Calendar/20130324*)
end tell
Result:
true



Can you look into the following path if you see a corestorage.ics file?

I could not find any 'corestorage.ics' file at all on my system:
Code:
[localhost]$ sudo find / -type f -name corestorage.ics
Password:
[localhost]$

But I found where all the calendars are stored. I sync my calendars to an OwnCloud server so the path is 'caldav' related. Comments in brackets () right to the file listing:

Calendar Root Directory
Code:
[COLOR="DarkRed"]/Users/ros/Library/Calendars/[/COLOR]
drwxr-xr-x  22 ros  staff      748 Mar 18 22:38 8E83A3AD-8EEF-4428-8203-2A4C67565E30.caldav		(All my personal calendars)
drwxr-xr-x   5 ros  staff      170 Oct  6 17:01 5DD3C270-985B-4C7A-AE57-399DB46CDDE6.calendar		(The 'Birthdays' calendar)

drwxr-xr-x   5 ros  staff      170 Oct  6 17:14 750D9A10-25FD-4CB7-9FA9-0464084CDBF5.caldav		(NotificationCollection)
drwxr-xr-x   4 ros  staff      136 Oct  6 15:54 C60C3148-EB8F-4929-B59E-9B0B8C6EF0EB.calendar		(Event Reminders)
-rw-r--r--@  1 ros  staff  7356416 Mar 24 12:25 Calendar Cache						(Binary File)
drwxr-xr-x  39 ros  staff     1326 Mar 24 12:02 Calendar Sync Changes					(Temp files)	
-rw-r--r--   1 ros  staff      182 Oct  6 17:14 Email Cache.plist					(Empty file)
drwxr-xr-x   2 ros  staff       68 Oct  6 16:16 Incoming						(Empty folder)

Calendar Directory for all my personal calendars
Code:
[COLOR="DarkRed"]/Users/ros/Library/Calendars/8E83A3AD-8EEF-4428-8203-2A4C67565E30.caldav/[/COLOR]
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 04950D7E-2BFA-4239-A349-24A573513B9E.calendar		(Education)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 3CAF1ED2-BE78-4A46-BC4D-E6C2BDD05B49.calendar		(Health)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 3F438A8D-EDDB-4FC0-861D-E5B2550A6D55.calendar		(Rest)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 4605849B-95A7-47B0-AEF3-39D6D04B7071.calendar		(Food)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 7CE2B1AD-C7E1-4DC8-86B6-62382364F678.calendar		(Location)	
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 86C2E0A3-46E2-4576-8D40-0027E409F593.calendar		(Holidays)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 94764D88-4D2E-4EF8-AE2D-042D805D847D.calendar		(Socialising)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 9C483337-B54C-4656-9AD4-D209418EDA33.calendar		(Employment)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 BEE64618-8AD9-4213-994C-A2EDA573082D.calendar		(Entertainment)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 CCF565CD-053B-479F-BE8D-EAC00681EA05.calendar		(Transport)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 D8B8EEC6-7963-4B9C-B759-97EA3EBD313C.calendar		(ToDo)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 DE09DCB3-11E5-481B-9825-8CC00EEDAD2B.calendar		(Hygiene)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 E4FD5C67-3BE5-4C0A-841F-E7AD244386B0.calendar		(Sports)
drwxr-xr-x    4 ros  staff   136 Mar 18 22:38 FE588D5A-A7A0-49B6-AA7A-1926468641ED.calendar		(Relationship)

drwxr-xr-x  121 ros  staff  4114 Mar 23 18:43 Attachments						(Empty folder)	
drwxr-xr-x    2 ros  staff    68 Feb 13 10:37 Inbox							(Empty folder)
-rw-r--r--@   1 ros  staff  1953 Mar 24 12:10 Info.plist						(CalDav setup details)
drwxr-xr-x    4 ros  staff   136 Oct  8 17:09 LocalDefaultAlarms					(Alarm related details)
drwxr-xr-x    2 ros  staff    68 Oct  6 17:14 NotificationCollection					(Empty folder)
drwxr-xr-x    4 ros  staff   136 Oct  6 17:02 ServerDefaultAlarms					(Alarm related details)

Example Calendar Details for Calendar 'Education'
Code:
[COLOR="DarkRed"]/Users/ros/Library/Calendars/8E83A3AD-8EEF-4428-8203-2A4C67565E30.caldav/04950D7E-2BFA-4239-A349-24A573513B9E.calendar/[/COLOR] 
	drwxr-xr-x  91 ros  staff  3094 Mar 19 23:05 Events
	-rw-r--r--   1 ros  staff  1169 Mar 24 11:45 Info.plist

Example Info.plist for Calendar 'Education' (snipped details)
Code:
[COLOR="DarkRed"]/Users/ros/Library/Calendars/8E83A3AD-8EEF-4428-8203-2A4C67565E30.caldav/04950D7E-2BFA-4239-A349-24A573513B9E.calendar/Info.plist[/COLOR] 
		...
        <key>Key</key>
        <string>04950D7E-2BFA-4239-A349-24A573513B9E</string>
		...
        <key>Title</key>
        <string>Education</string>
		...

Calendar Events for Calendar 'Education' (just a short selection of hundred of .ics files):
Code:
[COLOR="DarkRed"]/Users/ros/Library/Calendars/8E83A3AD-8EEF-4428-8203-2A4C67565E30.caldav/04950D7E-2BFA-4239-A349-24A573513B9E.calendar/Events/[/COLOR]
-rw-r--r--   1 ros  staff  1041 Mar 18 22:38 042597A8-26B1-4DAF-8B40-56314C666062.ics
-rw-r--r--   1 ros  staff  1041 Mar 18 22:38 0A69923B-2EEF-4D6A-A187-5CFB94C30026.ics
-rw-r--r--   1 ros  staff  1085 Mar 18 22:38 0F476A80-364D-456C-BE31-A894334A4A31.ics
-rw-r--r--   1 ros  staff  1039 Mar 18 22:38 158904AF-C32B-4814-B006-DC704D0465BD.ics
-rw-r--r--   1 ros  staff  1041 Mar 18 22:38 18A199AE-92DC-453F-935A-8B162711854A.ics
...
 

kryten2

macrumors 65816
Mar 17, 2012
1,114
99
Belgium
Thanks for the effort you are putting into helping me!

Sorry it's been a while. Can you try this :

Code:
-- Selecting calendars in iCal and export using GUI scripting
-- Change the backup_folder path!
-- Don't click anywhere else when the srcipt is running!

set timeStamp to do shell script "date \"+%Y%m%d\""
set backup_folder to "/Users/kryten/Backup/Calendar/"
do shell script "mkdir -p " & quoted form of backup_folder & quoted form of timeStamp
set savePath to backup_folder & timeStamp

-- Begin script
tell application "Calendar"
	launch
	activate
	delay 1
	set calNames to name of every calendar
end tell

tell application "System Events"
	tell process "Calendar"
		
		-- Left-hand menu of iCal, containing named calendars	
		set myOutline to outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of splitter group 1 of window "Calendar"
		set allRows to rows of myOutline
		
		-- List of named calendars
		set calNameVals to value of text field of every row in myOutline
		
		-- For all named calendars, check whether it's the same name as one of calNames
		-- If so, export that calendar.
		
		set countLoop to 0
		repeat with i from 2 to (count calNameVals)
			set countLoop to countLoop + 1
			set calName to item 1 of item i of calNameVals
			repeat with myName in calNames
				if (myName as string = calName as string) then
					tell row i of myOutline
						select
						delay 1
					end tell
					click menu item "Export…" of menu 1 of menu item "Export" of menu 1 of menu bar item "File" of menu bar 1
					delay 2
					if countLoop = 1 then
						keystroke "g" using {command down, shift down}
						delay 1
						keystroke savePath
						delay 1
						click button "Go" of sheet 1 of sheet 1 of window 1
					end if
					click button "Export" of sheet 1 of window 1
				end if
			end repeat
		end repeat
	end tell
end tell
 

Attachments

  • LowQualityScreenrecording.zip
    2.4 MB · Views: 353

Schubi

macrumors newbie
Original poster
Mar 22, 2013
19
0
Sorry it's been a while. Can you try this :
Like a clock-work! Thank you very much!

I'm pretty sure this will be helpful to a lot of other people as well - pity that such a basic function isn't implemented in Mountain Lion!
 

bcarpenter

macrumors newbie
Dec 30, 2008
5
0
This is great. Thanks!

I'd been previously saving my local (non-iCloud) calendars using an Applescript using a Calendar Archive, so scripting was relatively easy. Your method should also work for iCloud-based calendar backups, since these calendars aren't included in Calendar Archives.

However, I have struck a problem trying to implement your script if the Calendar application is actively updating subscribed calendars. In this situation, the window isn't called "Calendar. It's called "Calendar — Updating…".

How would I modify the script to select either window, bearing in mind that the name may change midway through the script execution?

Thanks.
 

Schubi

macrumors newbie
Original poster
Mar 22, 2013
19
0
Attaching the Mountain Lion script. Please rename .txt to .scpt in order to run it from the Script Editor.app. Don't forget to enable access for assistive devices and applications.

If you are looking for a script that runs under 10.9, please check the following thread: Mavericks Calendar - exporting calendars as .ics files
 

Attachments

  • OSX_10.8_Backup.txt
    8.9 KB · Views: 373
Last edited:
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.