跳至主要內容
技術

macOS defaults 備份別踩坑:為什麼 5.3MB 的 plist 不如 130 行的 shell script

macOS defaults 備份別踩坑:為什麼 5.3MB 的 plist 不如 130 行的 shell script
一鍵搞定新 Mac 第 9 / 9 篇

本篇是「一鍵搞定新 Mac」系列的第 9 / 9 篇。你可以從系列總覽開始閱讀,也可以直接接著看本文。

最近在整理我的 dotfiles,準備讓新電腦能「一鍵安裝」。用的是 chezmoi 管設定檔、Brewfile 管軟體安裝,整套流程已經跑得很順了。

但有一件事我一直沒搞定:macOS 的系統偏好設定。

每次換電腦,Dock 要重新設、Finder 要重新調、鍵盤重複速度要重新改⋯⋯這些瑣碎的設定加起來,大概要花半小時到一小時。

所以我想:不如用 defaults export 把整台電腦的設定匯出成 plist,跟 dotfiles 放在一起不就好了?

背景

一個完整的 macOS 開發環境大概有這三層:

層級內容負責工具
軟體安裝CLI 工具、桌面 AppHomebrew (Brewfile)
系統設定dotfiles、shell config、Git configchezmoi
macOS 偏好設定Dock、Finder、鍵盤速度⋯???

前兩層我都解決了,第三層一直是空的。defaults export 看起來就是那個完美答案。

發現過程

我跑了這個指令把全部 domain 匯出:

# 把所有 domain 的 user defaults 一次 dump 出來
# 注意:defaults export -g 只會匯出 NSGlobalDomain「一個」domain,不是全部;
# 要看到全部 domain 得用無參數的 defaults read(或對 defaults domains 列出的每個 domain 逐一 export)
defaults read > ~/macos-defaults-backup.txt

得到一個 5.3MB 的備份檔。

把它加進 dotfiles repo 之前,我先用 Claude Code 分析了一下內容。這一看嚇了一跳。

裡面到底有什麼?

這個 plist 包含 1,363 個 domain,大致分成四類:

1. 系統全域設定(你真正想要的)

Apple Global Domain → AppleInterfaceStyle = Dark
                    → KeyRepeat = 2
                    → InitialKeyRepeat = 15

Dock 大小、鍵盤速度、深色模式之類的設定。大概佔不到 5%。

2. Apple 原生 App 設定(部分有用)

com.apple.dock   → autohide = true, tilesize = 48
com.apple.finder → ShowPathbar = true

Finder、Dock、Safari 的開發者工具⋯⋯這些也是你會想帶到新機的設定。

3. 第三方 App 的私有資料(大量雜訊)

Microsoft Edge 的 A/B test flight flags(上千個實驗旗標)、Mixpanel tracking tokens、各種 app 的 session 狀態⋯⋯這些佔了整個檔案 90% 以上的體積,而且搬到新機器上完全沒意義。

4. 機敏資料(不該公開的東西)

這是最嚇人的部分:

資料類型內容範例
廣告 IDadvertisingId = 112e622f...
搜尋 client IDsearchClientId = 30754106...
GPS 座標location = "339550.0&5376927.4"
Session tokens多個 App 的登入 token
iCloud sync tokensApple 服務的同步 token

如果我就這樣 push 到 public GitHub repo⋯⋯嗯,不敢想。

具體數據 / 結果

方案檔案大小Domain 數可讀性隱私風險
defaults export plist5.3 MB1,363極差(二進位 + 雜訊)高(含 GPS、token)
手寫 defaults.sh3 KB~15極佳(每行有註解)

5.3MB 的全量匯出,不如 130 行的手寫 script。

我的 macos/defaults.sh 長這樣(節錄):

#!/bin/bash

# 加快鍵盤重複速度
defaults write NSGlobalDomain KeyRepeat -int 2
defaults write NSGlobalDomain InitialKeyRepeat -int 15

# 停用自動修正(寫程式不需要)
defaults write NSGlobalDomain NSAutomaticSpellingCorrectionEnabled -bool false

# 自動隱藏 Dock
defaults write com.apple.dock autohide -bool true
defaults write com.apple.dock tilesize -int 48

# 顯示隱藏檔案
defaults write com.apple.finder AppleShowAllFiles -bool true

# 顯示路徑列
defaults write com.apple.finder ShowPathbar -bool true

# 重啟相關服務
killall Dock 2>/dev/null || true
killall Finder 2>/dev/null || true

每一行都看得懂在幹嘛,而且只設定我「真正在意」的東西。

那原始 plist 要怎麼用?

我把它留在 repo 裡,但標記為「查閱用參考」而不是「直接匯入用」。如果換了新電腦後發現少了什麼設定,可以在 plist 裡搜尋對應的 key,然後手動加到 defaults.sh

# 在 plist 裡找特定設定
grep -i "screenshot" ~/macos-defaults-backup.plist

同時把它加進 .gitignore,不 commit 到 public repo:

echo "macos-defaults-backup.plist" >> .gitignore

反思

技術面

defaults export 就像 mysqldump 不加 --where——它忠實地把所有東西都倒出來,但大部分你不需要,有些還有害。

正確做法是手動挑選你在意的設定,寫成一個 shell script。好處:

  • 可讀:每行有註解,未來的自己看得懂在幹嘛
  • 可控:只動你確定知道效果的設定,不會有意外
  • 安全:不會意外洩漏隱私資料
  • 可移植:不同 macOS 版本之間相容性更好(全量 plist 有時候會帶入跟版本綁定的設定)

如果想參考別人精選的設定,mathiasbynens/dotfiles.macos 是業界常用的參考範本。

心態面

工程師很容易有「既然能自動化,就全部自動化」的衝動。但有些事情,精心挑選比全量匯出更有價值

dotfiles 的精髓不是「把舊電腦複製一份」,而是「把你的偏好用程式碼表達出來」。就像你不會把整個 node_modules commit 進 repo,你也不該把整台電腦的 defaults 無腦倒出來。

有趣發現

  • Microsoft Edge 光是 A/B test 的 flight flags 就是一整面字串,佔了 plist 裡面巨大的篇幅
  • 我發現自己裝了一個叫 AnswerDesign.EyeLoveU 的番茄鐘 App,設定是 work 20min / rest 5min,完全不記得什麼時候裝的
  • plist 裡面有 com.bobo52310.notionboard.settings——是我自己開發的 App,看到自己的 bundle ID 出現在系統 defaults 裡面,有種奇妙的感覺

留言討論

esc
輸入關鍵字搜尋文章...
查看收藏 →