├── Backup Ulysses on Quit (all in one).kmmacros
├── Backup-Ulysses-on-Quit.jpg
├── Backup-Ulysses-on-Quit.kmmacros
├── README.md
├── backup-ulysses-simpler.sh
└── backup-ulysses.sh
/Backup Ulysses on Quit (all in one).kmmacros:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Activate
7 | Normal
8 | CreationDate
9 | 459387347.72605699
10 | IsActive
11 |
12 | Macros
13 |
14 |
15 | Actions
16 |
17 |
18 | DisplayKind
19 | None
20 | IncludeStdErr
21 |
22 | IsActive
23 |
24 | IsDisclosed
25 |
26 | MacroActionType
27 | ExecuteShellScript
28 | Path
29 | /usr/local/scripts/backup-ulysses.sh
30 | Text
31 | #!/bin/zsh -f
32 | # Purpose: Make extra Ulysses backups because you're paranoid. No I'm not. Yes you are. Ok, yeah, that's fair.
33 | #
34 | #
35 | # I sent an earlier version of this to the Ulysses developers, and was told:
36 | # "It sounds like the only thing that can harm your texts now is a zombie apocalypse at
37 | # the Dropbox headquarters or the heat death of the universe."
38 | #
39 | #
40 | #
41 | # From: Timothy J. Luoma
42 | # Mail: luomat at gmail dot com
43 | # Date: 2016-03-09
44 |
45 |
46 | # This is where the archives will be saved when finishes
47 | # it will be created if it does not exist
48 | ARCHIVE_DIR="$HOME/Dropbox/Backups/Ulysses/"
49 |
50 |
51 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
52 | #
53 | # You should not need to change anything below this line,
54 | # although you are welcome to if you know what you are doing.
55 | #
56 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
57 |
58 |
59 | # short name of this file without path or extension
60 | NAME="backup-ulysses"
61 |
62 | if [ -e "$HOME/.path" ]
63 | then
64 | source "$HOME/.path"
65 | else
66 | PATH='/usr/local/scripts:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin'
67 | fi
68 |
69 | zmodload zsh/datetime
70 |
71 | TIME=`strftime "%Y-%m-%d--%H.%M.%S" "$EPOCHSECONDS"`
72 |
73 | function timestamp { strftime "%Y-%m-%d--%H.%M.%S" "$EPOCHSECONDS" }
74 |
75 | LOG="$HOME/Library/Logs/$NAME.log"
76 |
77 | function msg {
78 |
79 | echo "$NAME: $@" | tee -a "$LOG"
80 |
81 | # If growlnotify is installed in $PATH
82 | # use it to report messages
83 | if (( $+commands[growlnotify] ))
84 | then
85 |
86 | growlnotify \
87 | --appIcon "Ulysses" \
88 | --identifier "$NAME" \
89 | --message "$@" \
90 | --title "$NAME"
91 | fi
92 |
93 | }
94 |
95 |
96 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
97 | #
98 | # make sure the folder that we want to backup actually exists
99 | #
100 |
101 | cd "$HOME/Library/Containers"
102 |
103 | if [ ! -d "com.soulmen.ulysses3" ]
104 | then
105 | msg "No com.soulmen.ulysses3 found in $PWD"
106 | exit 0
107 | fi
108 |
109 |
110 |
111 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
112 | #
113 | # This is where we actually create the backup of the folder
114 | #
115 | # The filename will be something like this:
116 | #
117 | # com.soulmen.ulysses3.2016-03-09--16.52.51.tar.xz
118 | #
119 | # for March 9th at 4:52pm
120 |
121 | if (( $+commands[xz] ))
122 | then
123 |
124 | ARCHIVE="com.soulmen.ulysses3.`timestamp`.tar.xz"
125 |
126 | tar \
127 | --options='xz:compression-level=9' \
128 | --xz \
129 | --verbose \
130 | -c \
131 | -f "$ARCHIVE" \
132 | "com.soulmen.ulysses3"
133 |
134 | else
135 |
136 | ARCHIVE="com.soulmen.ulysses3.`timestamp`.tar.bz2"
137 |
138 | tar \
139 | --verbose \
140 | -y \
141 | -c \
142 | -f "$ARCHIVE" \
143 | "com.soulmen.ulysses3"
144 |
145 | fi
146 |
147 |
148 | EXIT="$?"
149 |
150 | if [ "$EXIT" != "0" ]
151 | then
152 | msg "tar failed (\$EXIT = $EXIT)"
153 |
154 | exit 0
155 | fi
156 |
157 |
158 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
159 | ##
160 | ## Move the .tar.xz pr .tar.bz2 file to the 'ARCHIVE_DIR'
161 | ## which is defined above
162 | ##
163 |
164 |
165 | [[ ! -d "$ARCHIVE_DIR" ]] && mkdir -p "$ARCHIVE_DIR"
166 |
167 | mv "$ARCHIVE" "$ARCHIVE_DIR" 2>&1 | tee -a "$LOG"
168 |
169 | EXIT="$?"
170 |
171 | if [ "$EXIT" = "0" ]
172 | then
173 | msg "Ran Successfully"
174 | else
175 | msg "FAILED Created $ARCHIVE but failed to move it to $ARCHIVE_DIR"
176 | fi
177 |
178 |
179 |
180 | exit 0
181 | #EOF
182 |
183 | TimeOutAbortsMacro
184 |
185 | TrimResults
186 |
187 | TrimResultsNew
188 |
189 | UseText
190 |
191 |
192 |
193 | CreationDate
194 | 480060183.58307898
195 | IsActive
196 |
197 | ModificationDate
198 | 482322360.98100501
199 | Name
200 | Backup Ulysses on Quit
201 | Triggers
202 |
203 |
204 | Application
205 |
206 | BundleIdentifier
207 | com.soulmen.ulysses3
208 | Name
209 | Ulysses
210 | NewFile
211 | /Applications/Ulysses.app
212 |
213 | FireType2
214 | Quit
215 | MacroTriggerType
216 | Application
217 | RepeatTime
218 | 60
219 | Target
220 | Specific
221 |
222 |
223 | UID
224 | D5F8DF7B-4E68-4859-B2B2-BCA5D1455C81
225 |
226 |
227 | Name
228 | Global Macro Group
229 | ToggleMacroUID
230 | 4948A9C1-5CD3-4AA1-A25D-9D29C5471ED8
231 | UID
232 | DA8512F7-F323-46B1-8319-752E0495CFD0
233 |
234 |
235 |
236 |
--------------------------------------------------------------------------------
/Backup-Ulysses-on-Quit.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tjluoma/backup-ulysses/61b6d2b7cffc7f682b2b7826f5ba6c2ff5b3b54b/Backup-Ulysses-on-Quit.jpg
--------------------------------------------------------------------------------
/Backup-Ulysses-on-Quit.kmmacros:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Activate
7 | Normal
8 | CreationDate
9 | 459387347.72605699
10 | IsActive
11 |
12 | Macros
13 |
14 |
15 | Actions
16 |
17 |
18 | DisplayKind
19 | Briefly
20 | IncludeStdErr
21 |
22 | IsActive
23 |
24 | IsDisclosed
25 |
26 | MacroActionType
27 | ExecuteShellScript
28 | Path
29 | /usr/local/scripts/backup-ulysses.sh
30 | Text
31 |
32 | TimeOutAbortsMacro
33 |
34 | TrimResults
35 |
36 | TrimResultsNew
37 |
38 | UseText
39 |
40 |
41 |
42 | CreationDate
43 | 0.0
44 | IsActive
45 |
46 | ModificationDate
47 | 479846975.57548499
48 | Name
49 | Backup Ulysses on Quit
50 | Triggers
51 |
52 |
53 | Application
54 |
55 | BundleIdentifier
56 | com.soulmen.ulysses3
57 | Name
58 | Ulysses
59 | NewFile
60 | /Applications/Ulysses.app
61 |
62 | FireType2
63 | Quit
64 | MacroTriggerType
65 | Application
66 | RepeatTime
67 | 60
68 | Target
69 | Specific
70 |
71 |
72 | UID
73 | D5F8DF7B-4E68-4859-B2B2-BCA5D1455C81
74 |
75 |
76 | Name
77 | Global Macro Group
78 | ToggleMacroUID
79 | 4948A9C1-5CD3-4AA1-A25D-9D29C5471ED8
80 | UID
81 | DA8512F7-F323-46B1-8319-752E0495CFD0
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # backup-ulysses
2 |
3 | Backup your entire Ulysses preferences folder (which includes your sheets, preferences, etc)
4 |
5 |
6 |
7 | ## Simpler Options (added 2016-04-14)
8 |
9 |
10 | `backup-ulysses-simpler.sh` and `Backup Ulysses on Quit (all in one).kmmacros` have been added to the repo.
11 |
12 | `Backup Ulysses on Quit (all in one).kmmacros` is a Keyboard Maestro macro that _already_ has the script `backup-ulysses-simpler.sh` embedded in it.
13 |
14 | Assuming you already have Keyboard Maestro installed, all you need to do is double-click on `Backup Ulysses on Quit (all in one).kmmacros` and it will be imported into your Keyboard Maestro setup.
15 |
16 | Every time the Ulysses app quits, the script will run, and a backup will be placed in ~/Dropbox/Backups/Ulysses.
17 |
18 | If you want it saved to a different location, all you have to do is edit the line
19 |
20 | `ARCHIVE_DIR="$HOME/Dropbox/Backups/Ulysses/"`
21 |
22 | in the script.
23 |
24 | (`$HOME` refers to your Mac OS X home directory, which is usually something like /Users/JSmith/ or /Users/JohnSmith/)
25 |
26 |
27 | ## Original Option
28 |
29 |
30 | Will use [dropbox_uploader.sh](https://github.com/andreafabrizi/Dropbox-Uploader/blob/master/dropbox_uploader.sh) if found, but can easily be used without it (see comments in script).
31 |
32 | Upon seeing this script, a Ulysses customer support representative stated to me:
33 |
34 | > It sounds like the only thing that can harm your texts now is a zombie apocalypse at the
35 | > Dropbox headquarters or the heat death of the universe.
36 |
37 | (Warning: Usual disclaimers apply, use at your own risk, etc etc.)
38 |
39 | ## How to use
40 |
41 | The easiest way to use this is to set up a [Keyboard Maestro](http://www.keyboardmaestro.com/main/) macro which runs every time [Ulysses](http://www.ulyssesapp.com/) quits, like so:
42 |
43 | 
44 |
45 | You can download and use
46 | [my Keyboard Maestro macro](https://raw.githubusercontent.com/tjluoma/backup-ulysses/master/Backup-Ulysses-on-Quit.kmmacros)
47 | if you wish, just be sure to change `/usr/local/scripts/backup-ulysses.sh` to the appropriate path on your Mac.
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/backup-ulysses-simpler.sh:
--------------------------------------------------------------------------------
1 | #!/bin/zsh -f
2 | # Purpose: Make extra Ulysses backups because you're paranoid. No I'm not. Yes you are. Ok, yeah, that's fair.
3 | #
4 | #
5 | # I sent an earlier version of this to the Ulysses developers, and was told:
6 | # "It sounds like the only thing that can harm your texts now is a zombie apocalypse at
7 | # the Dropbox headquarters or the heat death of the universe."
8 | #
9 | #
10 | #
11 | # From: Timothy J. Luoma
12 | # Mail: luomat at gmail dot com
13 | # Date: 2016-03-09
14 |
15 |
16 | # This is where the archives will be saved when finishes
17 | # it will be created if it does not exist
18 | ARCHIVE_DIR="$HOME/Dropbox/Backups/Ulysses/"
19 |
20 |
21 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
22 | #
23 | # You should not need to change anything below this line,
24 | # although you are welcome to if you know what you are doing.
25 | #
26 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
27 |
28 |
29 | # short name of this file without path or extension
30 | NAME="backup-ulysses"
31 |
32 | if [ -e "$HOME/.path" ]
33 | then
34 | source "$HOME/.path"
35 | else
36 | PATH='/usr/local/scripts:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin'
37 | fi
38 |
39 | zmodload zsh/datetime
40 |
41 | TIME=`strftime "%Y-%m-%d--%H.%M.%S" "$EPOCHSECONDS"`
42 |
43 | function timestamp { strftime "%Y-%m-%d--%H.%M.%S" "$EPOCHSECONDS" }
44 |
45 | LOG="$HOME/Library/Logs/$NAME.log"
46 |
47 | function msg {
48 |
49 | echo "$NAME: $@" | tee -a "$LOG"
50 |
51 | # If growlnotify is installed in $PATH
52 | # use it to report messages
53 | if (( $+commands[growlnotify] ))
54 | then
55 |
56 | growlnotify \
57 | --appIcon "Ulysses" \
58 | --identifier "$NAME" \
59 | --message "$@" \
60 | --title "$NAME"
61 | fi
62 |
63 | }
64 |
65 |
66 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
67 | #
68 | # make sure the folder that we want to backup actually exists
69 | #
70 |
71 | cd "$HOME/Library/Containers"
72 |
73 | if [ ! -d "com.soulmen.ulysses3" ]
74 | then
75 | msg "No com.soulmen.ulysses3 found in $PWD"
76 | exit 0
77 | fi
78 |
79 |
80 |
81 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
82 | #
83 | # This is where we actually create the backup of the folder
84 | #
85 | # The filename will be something like this:
86 | #
87 | # com.soulmen.ulysses3.2016-03-09--16.52.51.tar.xz
88 | #
89 | # for March 9th at 4:52pm
90 |
91 | if (( $+commands[xz] ))
92 | then
93 |
94 | ARCHIVE="com.soulmen.ulysses3.`timestamp`.tar.xz"
95 |
96 | tar \
97 | --options='xz:compression-level=9' \
98 | --xz \
99 | --verbose \
100 | -c \
101 | -f "$ARCHIVE" \
102 | "com.soulmen.ulysses3"
103 |
104 | else
105 |
106 | ARCHIVE="com.soulmen.ulysses3.`timestamp`.tar.bz2"
107 |
108 | tar \
109 | --verbose \
110 | -y \
111 | -c \
112 | -f "$ARCHIVE" \
113 | "com.soulmen.ulysses3"
114 |
115 | fi
116 |
117 |
118 | EXIT="$?"
119 |
120 | if [ "$EXIT" != "0" ]
121 | then
122 | msg "tar failed (\$EXIT = $EXIT)"
123 |
124 | exit 0
125 | fi
126 |
127 |
128 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
129 | ##
130 | ## Move the .tar.xz pr .tar.bz2 file to the 'ARCHIVE_DIR'
131 | ## which is defined above
132 | ##
133 |
134 |
135 | [[ ! -d "$ARCHIVE_DIR" ]] && mkdir -p "$ARCHIVE_DIR"
136 |
137 | mv "$ARCHIVE" "$ARCHIVE_DIR" 2>&1 | tee -a "$LOG"
138 |
139 | EXIT="$?"
140 |
141 | if [ "$EXIT" = "0" ]
142 | then
143 | msg "Saved $ARCHIVE to $ARCHIVE_DIR"
144 | else
145 | msg "Created $ARCHIVE but failed to move it to $ARCHIVE_DIR"
146 | fi
147 |
148 |
149 |
150 | exit 0
151 | #EOF
152 |
--------------------------------------------------------------------------------
/backup-ulysses.sh:
--------------------------------------------------------------------------------
1 | #!/bin/zsh -f
2 | # Purpose: Make extra Ulysses backups because you're paranoid. No I'm not. Yes you are. Ok, yeah, that's fair.
3 | #
4 | # From: Timothy J. Luoma
5 | # Mail: luomat at gmail dot com
6 | # Date: 2016-03-09
7 |
8 |
9 | # this is the directory where backup files will be moved _to_ after they are created
10 | # You will almost certainly want to change this
11 | ARCHIVE_DIR='/Volumes/Data/Backups/Ulysses/'
12 |
13 | ## If you want to just move the backup to your Dropbox folder,
14 | ## just uncomment the next line and set it to the proper path
15 |
16 | # ARCHIVE_DIR=/path/to/Dropbox/Backups/Ulysses/
17 |
18 |
19 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
20 | #
21 | # if 'dropbox_uploader.sh' exists, use it to upload a copy to
22 | # a folder in Dropbox. In my case the folder name is
23 | #
24 | # ~/Dropbox/NoSync/Ulysses-Backups/
25 | #
26 | # but for dropbox_uploader.sh we just need the '/NoSync/Ulysses-Backups/' part
27 |
28 | DROPBOX_DIR='/NoSync/Ulysses-Backups/'
29 |
30 |
31 |
32 |
33 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
34 | #
35 | # You should not need to change anything below this line,
36 | # although you are welcome to if you know what you are doing.
37 | #
38 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
39 |
40 |
41 | # short name of this file without path or extension
42 | NAME="$0:t:r"
43 |
44 | if [ -e "$HOME/.path" ]
45 | then
46 | source "$HOME/.path"
47 | else
48 | PATH='/usr/local/scripts:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin'
49 | fi
50 |
51 | zmodload zsh/datetime
52 |
53 | TIME=`strftime "%Y-%m-%d--%H.%M.%S" "$EPOCHSECONDS"`
54 |
55 | function timestamp { strftime "%Y-%m-%d--%H.%M.%S" "$EPOCHSECONDS" }
56 |
57 | LOG="$HOME/Library/Logs/$NAME.log"
58 |
59 | function msg {
60 |
61 | echo "$NAME: $@" | tee -a "$LOG"
62 |
63 | if (( $+commands[po.sh] ))
64 | then
65 |
66 | po.sh "$NAME: $@"
67 |
68 | fi
69 | }
70 |
71 |
72 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
73 | #
74 | # make sure the folder that we want to backup actually exists
75 | #
76 |
77 | cd "$HOME/Library/Containers"
78 |
79 | if [ ! -d "com.soulmen.ulysses3" ]
80 | then
81 | msg "No com.soulmen.ulysses3 found in $PWD"
82 | exit 0
83 | fi
84 |
85 |
86 |
87 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
88 | #
89 | # This is where we actually create the backup of the folder
90 | #
91 | # The filename will be something like this:
92 | #
93 | # com.soulmen.ulysses3.2016-03-09--16.52.51.tar.xz
94 | #
95 | # for March 9th at 4:52pm
96 |
97 | if (( $+commands[xz] ))
98 | then
99 |
100 | ARCHIVE="com.soulmen.ulysses3.`timestamp`.tar.xz"
101 |
102 | tar \
103 | --options='xz:compression-level=9' \
104 | --xz \
105 | --verbose \
106 | -c \
107 | -f "$ARCHIVE" \
108 | "com.soulmen.ulysses3"
109 |
110 | else
111 |
112 | ARCHIVE="com.soulmen.ulysses3.`timestamp`.tar.bz2"
113 |
114 | tar \
115 | --verbose \
116 | -y \
117 | -c \
118 | -f "$ARCHIVE" \
119 | "com.soulmen.ulysses3"
120 |
121 | fi
122 |
123 |
124 | EXIT="$?"
125 |
126 | if [ "$EXIT" != "0" ]
127 | then
128 | msg "tar failed (\$EXIT = $EXIT)"
129 |
130 | exit 0
131 | fi
132 |
133 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
134 | #
135 | # if 'dropbox_uploader.sh' exists, use it to upload a copy to
136 | # a folder in Dropbox.
137 |
138 | if (( $+commands[dropbox_uploader.sh] ))
139 | then
140 |
141 | dropbox_uploader.sh -s -p upload "$ARCHIVE" "$DROPBOX_DIR" 2>&1 | tee -a "$LOG"
142 |
143 | EXIT="$?"
144 |
145 | if [ "$EXIT" != "0" ]
146 | then
147 | msg "Failed to upload $ARCHIVE to Dropbox dir: $DROPBOX_DIR (EXIT = $EXIT)"
148 | fi
149 | fi
150 |
151 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|####
152 | #
153 | # Move the .tar.xz file to the 'ARCHIVE_DIR' defined above
154 | #
155 |
156 | mv "$ARCHIVE" "$ARCHIVE_DIR" 2>&1 | tee -a "$LOG"
157 |
158 | EXIT="$?"
159 |
160 | if [ "$EXIT" = "0" ]
161 | then
162 | msg "Saved $ARCHIVE to $ARCHIVE_DIR"
163 | else
164 | msg "Created $ARCHIVE but failed to move it to $ARCHIVE_DIR"
165 | fi
166 |
167 |
168 |
169 | exit 0
170 | #EOF
171 |
--------------------------------------------------------------------------------