screencap.sh

UPDATE: This stopped working for me with macOS Catalina.
FURTHER UPDATE: I’m now using Rewind.ai for this.

You know how sometimes a blog or web form eats your comment or you lose some text and break your undo history or something and you wish you could rewind and see what was on your screen some minutes or hours ago? I made a script to do that that has saved my butt (or a bunch of hassle) more than once. It’s also handy for checking things like what time you left the office.

Here it is:

#!/bin/bash
# By dreev, written maybe 2017, last edited 2019 or 2020

# Instructions:
# Cron this like so to save screenshots aka screencaps every minute:
#   * * * * * /full/path/to/this/script.sh
# Screenshots older than 24 hours will get overwritten by new ones and the whole
# collection should be at most a gigabyte or so if the jpeg quality is kept low.
# Filenames are eg screen1cap-13-59.jpg for a screencap of display 1 at 1:59pm.

jq=20;  # jpeg quality (20 seems always readable, 10 not always for small fonts)
scap="/usr/sbin/screencapture";    # standard macOS screenshot tool
mogr="/usr/local/bin/mogrify";     # part of ImageMagick for transforming images
path="~/tmp/screenshots";          # where all the screenshots live
t=$(/bin/date +%s)                 # current time as unixtime
hm=$(/bin/date +%H-%M);            # eg "19-59" when it's 7:59pm

# get the number of connected, online displays (not needed currently) 
#n=`/usr/sbin/system_profiler SPDisplaysDataType | grep -c 'Online: Yes'`;

f1="$path/screen1cap-$hm.jpg"
f2="$path/screen2cap-$hm.jpg"
f3="$path/screen3cap-$hm.jpg"

# grab a screenshot for every monitor (up to 3 currently; add more to taste)
$scap -x -d -r -T0 -tjpg $f1 $f2 $f3

/bin/sleep 1 # make sure the screencapture is done

t1=$(/bin/date -r $f1 +%s)
t2=$(/bin/date -r $f2 +%s)
t3=$(/bin/date -r $f3 +%s)

# drastically reduce the file sizes (for the ones just now created)
if [ $t1 -ge $t ] ; then $mogr -quality $jq $f1 &> /dev/null ; fi
if [ $t2 -ge $t ] ; then $mogr -quality $jq $f2 &> /dev/null ; fi
if [ $t3 -ge $t ] ; then $mogr -quality $jq $f3 &> /dev/null ; fi

Separately, here’s a bit of Mathematica code to touch all possible 24*60*numscreens files, if you don’t want missing files when the display is off. It’s safe to run any time — it only touches files that don’t exist. And the only reason to bother is that it can be handy for treating the screenshot timestamps as quantified-self data, like, “I’ve never been awake at 4am since I started running this on such-and-such date”.

# path = "~/tmp/screenshots/";
# each[s_, Range[1, 3],
#   each[h_, Range[0, 23],
#     each[m_, Range[0, 59],
#       f = cat[path, "screen", s, "cap-", If[h < 10, "0", ""], h, "-", 
#                                          If[m < 10, "0", ""], m, ".jpg"];
#       If[!FileExistsQ[f],
#         CreateFile[f];
#         SetFileDate[f, DateObject[{1970,1,1}]]  ]]]]