brokensandals.net -> Technical -> Backup Tooling -> Backing up Evernote to git

Update on 2020-04-28: I wrote an easily installed command-line tool for invoking Evernote export, in case you prefer that over copying a shell script.

Published 2016-09-10.

I love Evernote, but I don’t trust it to never lose my data. The Mac app syncs all your notes locally in an HTML format, so you can get some protection by doing automated backups of its folder (which is within ~/Library/Application Support/com.evernote.Evernote/accounts/www.evernote.com) with a backup service like CrashPlan.

I thought it would be nice to additionally commit the notes to a git repository. The script below will:

  1. Force Evernote to sync.
  2. Export notes in HTML format into a git repo, using separate subdirectories for each notebook, and commit the changes. (All files in the repo are git rm’d before starting the export, so that notes which no longer exist will be deleted in the commit.)
  3. Display a notification with stats about the commit.

example notification

I originally tried exporting using the enex file format instead - which dumps all data into one large file - but I found that the repo’s size grew out of control due to excessive changes in that output. This hasn’t been an issue with the HTML export so far, even though updates to the application do sometimes cause a large number of the exported files to be altered. Since metadata like tags and created/updated time are included as meta tags in the exported HTML files, I don’t think anything important is lost by using the HTML format rather than the enex format.

You can set this up to run automatically by putting the launchd config below into ~/Library/LaunchAgents/ and either rebooting, or running launchctl load ~/Library/LaunchAgents/net.brokensandals.evernote.backup.html.plist.

(In this gist, backup_dir should be changed to point to an initialized, empty git repo where you want to store the exports, and /Users/jacob/dotfiles/bin/backup-evernote-html.sh should be replaced with wherever you install the script.)

#!/bin/bash
backup_dir=/Users/jacob/Backup/evernote-html
# thanks to http://veritrope.com/code/get-note-links-in-evernote-for-newly-created-notes/ for how to wait for sync to finish
osascript <<END
with timeout of (30 * 60) seconds
tell application "Evernote"
synchronize
repeat until isSynchronizing is false
delay 10
end repeat
end tell
end timeout
END
if [ $? -ne 0 ]; then
osascript -e "display notification \"Failed to force synchronization.\" with title \"Evernote Backup\""
exit 1
fi
cd $backup_dir
git rm -r .
osascript <<END
with timeout of (30 * 60) seconds
tell application "Evernote"
repeat with curNotebook in (every notebook)
if (count of notes of curNotebook) > 0 then
set notebookBackupDir to ("$backup_dir/" & (name of curNotebook))
do shell script ("mkdir -p " & notebookBackupDir)
export (find notes ("notebook:" & (name of curNotebook))) to notebookBackupDir format HTML
end if
end repeat
end tell
end timeout
END
if [ $? -ne 0 ]; then
osascript -e "display notification \"Failed to export notes.\" with title \"Evernote Backup\""
exit 1
fi
cd $backup_dir
git add .
git commit -m "$(date) from backup script"
if [ $? -eq 0 ]; then
changes=$(git show --stat HEAD | grep changed)
else
changes="No changes."
fi
git gc
osascript -e "display notification \"$changes\" with title \"Evernote Backup\" subtitle \"HTML export completed.\""
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>net.brokensandals.evernote.backup.html</string>
<key>Program</key>
<string>/Users/jacob/dotfiles/bin/backup-evernote-html.sh</string>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>4</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
</dict>
</plist>