1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
#!/bin/bash
# Find the `defaults` key behind a setting you changed in System Settings, so it
# can go in macos-defaults.sh instead of being remembered.
#
# macos-defaults-diff snapshot, wait while you change one setting,
# then print what moved
# macos-defaults-diff snap take the snapshot only
# macos-defaults-diff show compare now against the last snapshot
#
# It reads both the global domains and the per-host ones (`-currentHost`), which
# is where several trackpad, mouse and font settings live and which a plain
# `defaults read` never shows.
#
# Change ONE setting at a time. macOS writes unrelated keys constantly -- window
# positions, recent items, sidebar widths -- so a diff after three changes is
# mostly noise with your key hidden in it.
#
# Quit System Settings before the second snapshot. It holds changes in memory
# and cfprefsd may not have written them yet; the line below flushes that cache.
#
# Runs under macOS's /bin/bash 3.2.
set -euo pipefail
if [[ "$(uname)" != "Darwin" ]]; then
>&2 echo "macos-defaults-diff: macOS only"
exit 1
fi
dir="${TMPDIR:-/tmp}/macos-defaults-diff"
mkdir -p "${dir}"
snapshot() {
local tag="$1"
# cfprefsd caches writes; without this a change made seconds ago can be
# missing from the read that is supposed to reveal it.
killall cfprefsd 2>/dev/null || true
sleep 1
defaults read > "${dir}/${tag}.txt" 2>/dev/null || true
defaults -currentHost read > "${dir}/${tag}-host.txt" 2>/dev/null || true
}
report() {
if [[ ! -f "${dir}/before.txt" ]]; then
>&2 echo "macos-defaults-diff: no snapshot yet -- run 'macos-defaults-diff snap' first"
exit 1
fi
snapshot after
local found=""
if ! diff -u "${dir}/before.txt" "${dir}/after.txt" > "${dir}/delta.txt" 2>&1; then
found=y
echo "=== global domains"
grep -E '^[+-]' "${dir}/delta.txt" | grep -vE '^(\+\+\+|---)' | sed 's/^/ /'
fi
if ! diff -u "${dir}/before-host.txt" "${dir}/after-host.txt" > "${dir}/delta-host.txt" 2>&1; then
found=y
echo "=== this host only -- these need 'defaults -currentHost write'"
grep -E '^[+-]' "${dir}/delta-host.txt" | grep -vE '^(\+\+\+|---)' | sed 's/^/ /'
fi
if [[ -z "${found}" ]]; then
echo "nothing changed."
echo "Some settings are not in defaults at all: anything behind Privacy &"
echo "Security lives in the SIP-protected TCC database, and a few panes use"
echo "private APIs. Those cannot be scripted -- note them in macos-defaults.sh"
echo "as manual steps instead."
return
fi
echo
echo "The domain is the nearest heading above the changed line in:"
echo " ${dir}/delta.txt"
echo "Write it as: defaults write <domain> \"<key>\" -bool/-int/-string <value>"
echo "then add it to macos-defaults.sh, and restart whatever owns it"
echo "(killall Dock, killall Finder, or log out)."
}
case "${1:-}" in
snap)
snapshot before
echo "snapshot taken. Change one setting, then: macos-defaults-diff show"
;;
show)
report
;;
"")
snapshot before
echo "Snapshot taken. Now change ONE setting in System Settings, quit it,"
printf 'then press Enter: '
read -r _
report
;;
-h|--help)
sed -n '3,21p' "$0" | sed 's/^# \{0,1\}//'
;;
*)
>&2 echo "macos-defaults-diff: unknown argument: $1"
exit 1
;;
esac
|