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:
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> |