--- /dev/null
+#!/bin/bash
+#
+# This is intended as an hourly cron script for rolling up timeliner
+# directories into tgz files. Each $DIR.tgz file contains only the
+# files in the $DIR directory tree that are not also contained in its
+# successor directory tree.
+
+# Specifically, since the timeliner creates the successive timeline
+# directory trees by hard-linking files, only files with inodes unique
+# to $DIR are packed into $DIR.tgz, while inodes also occurring in the
+# successor directory tree are ignored.
+#
+# The script is run with $BASE set for the directory that contains
+# timpliner directories to roll up. The script also ensures a file
+# lock on itself which is intended to block any possible run-in of a
+# later script execution on top of an ongoing execution.
+#
+# Normally the crontab entry invokes the script with a BASE
+# environment setting but without arguments. The script will then
+# re-execute itself in the $BASE directory with the directories
+# 2???-??-??/ on the command line.
+
+lsi() {
+ find "$1" -type f -print0 | xargs -0 ls -i
+}
+
+files() {
+ awk 'FNR == NR {L[$1 ""]="" $0 ; next} {delete L[$1 ""];next}
+ END { for (i in L) {print L[i]}}' <(lsi "$1") <(lsi "$2") | \
+ sed 's|^[^ ]* ||;\|^'"$1"'/|!d' | \
+ sort | tr '\012' '\000'
+}
+
+if [ -z "$BASE" ] ; then echo "BASE=... is required" >&2 ; exit 1 ; fi
+
+[ -z "$LOCKED" ] && exec env LOCKED=yes flock -E 0 -n "$0" "$0" "$@"
+
+cd "$BASE" || exit 1
+[ -z "$1" ] && exec "$0" $(ls -d 2???-??-??/)
+D="${1%/}"
+shift
+for X in "$@" ; do
+ X="${X%/}"
+ tar czf "$D.tgz" --null -T <(files "$D" "$X") || exit 1
+ rm -r "$D"
+ D="$X"
+done