Today’s post is a trivial script to pick a random screensaver every day on OS X. Yes, if you go the “Desktop & Screen Saver” preference pane, there is the last item called “Random”, but it’s very limited — a screensaver is picked randomly among all available every time when it’s requested. To show why that’s not what I need, let’s install a pack of great screensavers, which has been ported to OSX — XScreenSaver:
123
# run this command if you don't have `brew cask` installed yet$ brew tap caskroom/cask
$ brew cask install xscreensaver
Now, I don’t want to run some of the screensavers and none of the standard ones. Plus, I want one to be picked at random every day, not on every use. Check out “XAnalogTV”, “Substrate”, or “BSOD”.
What’s the current screensaver?
This article directed me to the right path by showing how to change the current screensaver from the command line: http://krypted.com/mac-security/mac-setting-screen-saver-from-the-cli/. I’m going to sometimes use PlistBuddy instead of defaults, because the former one is more modern and functional. PlistBuddy is located in /usr/libexec/, which is not included in $PATH by default, so let’s fix this with symlinking it into /usr/local/bin/ (which should be in $PATH if you’re using brew):
Here you see its name (moduleName) and path. We’ll need to update those values from our script. The ioreg … subcommand gets the host’s UUID to figure out the proper plist filename — that command is taken from this article: http://wranglingmacs.blogspot.com/2009/04/getting-byhost-string.html.
Setting a random screensaver
You can set a random xscreensaver from command line like this:
1234
# `coreutils` provides GNU versions of core utils, including `gshuf`, which is absent on OSX$ brew install coreutils
$ f=${$( ls -1 ~/Library/Screen\ Savers | gshuf -n1 )%.saver}; defaults -currentHost write com.apple.screensaver moduleDict '{"type"=0; "path"="'$HOME/Library/Screen\ Savers/$f.saver'"; "moduleName"='$f';}'
Now, I’d like to pick a random screensaver from a subset of all screensavers. So I’m listing the existing xscreensavers into a file, from which one will be selected:
1
$ ls -1d ~/Library/Screen\ Savers/*.saver | sed -E 's!.*/(.*)\.saver!\1!' > ~/.screensavers
(That’s a weird way of getting the base name, but basename doesn’t like spaces in names). You can remove ones you don’t want from the file now or later. And the setting script becomes a little shorter:
And the last step, autoupdate. We’ll use our old friend, crond daemon (I know, we should use launchd on OS X, which has crond features and more, but the config is more verbose, so I may upload it later if necessary). Add this line to your ~/.crontab file (a random screensaver is set at 09:00 every day):