# Is there a notebook autosave frequency configuration?

I've had Mathematica crash on me a number of times, and have had to recreate notebook contents from the last save point.

I was looking for something in the preferences like an autosave frequency configuration parameter that I could use to automatically save all my notebook content at some regular frequency to minimize losses due to crashes.

I found NotebookSave[], and a NotebookAutoSave -> True attribute for CreateDocument, but both these appear to be for manipulating external notebooks. Is there a way to do this systematically and by default?

-
I don't think there's such an option. In any case, this answer might be relevant for your needs. What it does is it saves a copy of the current notebook (with a .backup extension) upon every cell evaluation. –  rm -rf Nov 2 '12 at 5:08

You can set the NotebookAutoSave preference programmatically or via the Option Inspector.

To turn autosave on by default for all notebooks, you could do:

CurrentValue[$FrontEnd, "NotebookAutoSave"] = True  You can also set the option for individual notebooks by changing $FrontEnd to the appropriate notebook handle. According to the docs, NotebookAutoSave saves after every evaluation and seems to be inflexible in that regard.

-
Excellent. With that and checking in my notebooks to my git repository, I should have decent recoverability. I can always rollback to my last VCS commit (provided I explicitly commit after interesting changes) should I not like what has gotten autosaved, but should avoid losses due to unforeseen crashes. –  Peeter Joot Nov 3 '12 at 1:18

You could try executing

RunScheduledTask[
EmitSound[Sound[SoundNote[]]];NotebookSave[EvaluationNotebook[]], 10];


which saves the notebook every 10 seconds and plays a note.

-

I have a Mathematica package that provides auto-backup functionality. When enabled, the current notebook--call it "blah.nb"--will be backed up to "blah.nb~" after a configurable amount of time has elapsed. I use it constantly and it has saved me from losing work many, many times. It's better than autosaving since it doesn't touch the actual notebook file: if you screw something up or something gets corrupted you don't want to overwrite your main file. :)

It's on GitHub here.

-
This is really nice, thanks for that! –  Eoin Feb 3 at 10:34

Motivated by the same concerns, I wrote the following code and added it to my init.m file. There are two main entries you'll want to change to use this. The global variable $SwapDirectory is where the swap files are saved (by swap file, I mean it in the VIm sense; an "extra" copy of your notebook, separate from your manually saved copy that periodically saves any new work). The swap files are organized within the swap directory in a directory structure which "mirrors" their original file locations, and have ".swp" appended to their file names. The other variable you might want to change is the number of seconds between autosaves, indicated by the "300" (corresponding to 5 minutes) near the bottom of the code below. At the appropriate times, this code will (automatically in the background) save swap files for ALL open notebooks, unless they are unmodified from their manually-saved versions (this exception makes the code more efficient, and more importantly, prevents the storage of swap files for documentation notebooks, for example). Some things to note: 1) the Mathematica Put command seems to have trouble writing to network drives, even when offline access is enabled. Therefore, it is probably best to choose a SwapDirectory that is on your local machine. 2) Within SwapDirectory, you should create a sub-directory called "Recovery". This is where the AutoSaveSwap routine will make an initial save of any notebooks for which there is NO existing manual save location. 3) Recovering any given notebook is easy. Simply evaluate  RecoverSwap["filePath"]  where "filePath" is a string representing the filePath of the MANUALLY-SAVED copy of the file (i.e., not the file that was created by AutoSave). This will then pop up a window containing the most recent auto-saved version of the file. The manually saved version is NEVER overwritten, unless you explicitly choose to do so. Once the recovered version pops up, you can save it whereever you like, or discard it at your discretion. 4) You should probably add this code to the KERNEL version of init.m ($UserBaseDirectory/Kernel/init.m) rather than the frontend version... this way, if you quit and restart the kernel, the autosave feature will also restart. On the other hand, this means that you must evaluate at least one expression after each start or restart to begin auto-saving. Once this initial evaluation is done, you do NOT need to have evaluated a cell for it to be backed up (unlike the built-in autosave utility).

Hope this helps someone! Feel free to respond with any questions, suggestions, or requests for improvement you may have. And, if you find this post useful, upvotes would be most appeciated! Take care.


$SwapDirectory= "C:\\Users\\pacoj\\Swap Files\\"; SaveSwap[nb_NotebookObject]:=Module[ {fileName, swapFileName, nbout, nbdir, nbdirout, recoveryDir}, If[ ! SameQ[Quiet[NotebookFileName[nb]],$Failed],
(* if the notebook is already saved to the file system *)
fileName = Last[ FileNameSplit[ NotebookFileName[nb]] ];
swapFileName = fileName <> ".swp";
nbdir = Rest[FileNameSplit @ NotebookDirectory[nb]];
nbdirout= FileNameJoin[ FileNameSplit[$SwapDirectory]~Join~nbdir]<>"\\"; If[!DirectoryQ[nbdirout], CreateDirectory[nbdirout]]; nbout = NotebookGet[nb]; Put[nbout, nbdirout <> swapFileName], (* else, if the file has never been saved, save as untitled *) recoveryDir=$SwapDirectory <> "Recovery\\";
fileName= ("WindowTitle" /. NotebookInformation[nb])<>".nb";
NotebookSave[nb, recoveryDir <> fileName]
]
];
RecoverSwap[nbfilename_String]:=Module[
{fileName, swapFileName, nbin, nbdir, nbdirout},
fileName= Last[ FileNameSplit[ nbfilename] ];
swapFileName= fileName <> ".swp";
nbdir= Most[ Rest[FileNameSplit @ nbfilename] ];
nbdirout= FileNameJoin[ FileNameSplit[\$SwapDirectory]~Join~nbdir]<>"\\";
If[ FileNames[swapFileName, {nbdirout}] == {},
Message[RecoverSwap::noswp,nbdirout <> swapFileName]; Return[],
nbin= Get[nbdirout <> swapFileName]; NotebookPut[nbin]
]
];
StartScheduledTask[AutoSaveSwaps]