以 GNU Stow 來管理 dotfiles

作者:   發佈於:   #software

最近發現 GNU Stow 這個軟體,其主要提供的功能是以 symlink 來做到軟體安裝。其自我介紹文中第一段話為:

GNU Stow is a symlink farm manager which takes distinct packages of software and/or data located in separate directories on the filesystem, and makes them appear to be installed in the same place.

意思就是說:你可以用 GNU Stow 把本來裝在四處的資料或程式,以 symlink,讓它們看來好像是全裝在同一個目錄下。

乍看之下好像怪怪的沒有什麼用處(為何不一開始就裝在一起?)但轉念一想:這不就是 homebrew 的做法嗎?

看來 GNU Stow 所做的工作,就類似於 brew link 這個階段,把本來安奘在 A 處的各個檔案,逐一在 B 處建立相對應的 symlink。由於 B 處都是 symlink,要移除也相對簡單。並且,能以 symlink 內容作為某種安裝證明,不怕失誤刪到了不在管轄範圍內的物件。

這做法對於管理 $HOME 底下的 dotfile 十分有用。由於 dotfile 都是必須要放在 $HOME 底下指定位置的檔案,如果要以版本控制系統來管理,那就還要另外有一套方式去把那些檔案自版本控制系統中拷貝出來放在 $HOME 底下,如果還想要有簡單的同步或刪除機制的話,用 GNU Stow / symlink 似乎就很適合了。

以下用幾個簡單的範例來示範一下。首先是建一個 dotfiles/ 目錄,並在底下依照軟體名建立出若干子目錄。子目錄底下則是放置該軟體的 dotfile。並且,使其中 dotfile 路徑有保留住 $HOME 之後的部分。例如,如果某 abc 軟體的 dotfile 為 $HOME/.config/abc/abc.conf,那就把其 $HOME 的部分換為 dotfiles/abc/。也就是要建出 dotfiles/abc/.config/abc/abc.conf

如果是從既有的檔案移管,準備起來大致上像這樣:

mkdir -p dotfiles/zsh
cp ~/.zshrc ~/.zshenv dotfiles/zsh/

mkdir -p dotfiles/emacs/.emacs.d
cp ~/.emacs.d/init.el dotfiles/emacs/.emacs.d

mkdir -p dotfiles/sway/.config/sway/
cp ~/.config/sway/* dotfiles/sway/.config/sway/

mkdir -p dotfiles/wezterm/.config/wezterm/
cp ~/.config/wezterm/* dotfiles/wezterm/.config/wezterm/

dotfiles/ 準備完畢之後,就執行 stow

cd dotfiles

stow --target=$HOME zsh/
stow --target=$HOME emacs/
stow --target=$HOME sway/
stow --target=$HOME wezterm/

這麼一做完之後,原本 $HOME 底下的 dotfile 就會被 stow 改成是連到 dotfiles/ 目錄底下某個檔案的 symlink 了。

dotfiles/ 目錄本身就可以再透過 git init 等步驟來納入版本控制系統中,並且,其內容是依照各個軟體名分類放好了的。就算實際在 $HOME 底下會出現在很多子目錄,但在版本控制系統中是很一致的。

特別是在刪除的時候。有時候試用軟體要寫幾個 dotfile,一陣子沒用後,把軟體刪除了,但 dotfile 卻沒有一起清。久而久之就忘了那些在 $HOME 底下的 .abcrc.xyz.conf 倒底是有用還是已經沒用的了。變得想清理又會怕弄錯。

透過本文所述的管理方式,如果哪天想把軟體 abc 的 dotfile 全丟了,也不必再花心力去找出它的 dotfile 是 .abcrc.abc.confconfig/abc/abc.conf 還是什麼其他冷門的命名慣例,只要以 stow 指令:

stow --target=$HOME --delete abc/

就可以把當初安裝上的所有檔案一次清光了。

如果發現不小心刪錯了,再重跑一次 stow 就可以救回來。

GNU Stow 的機制簡單又合理。看來應該能讓管理個人的 dotfile 的過程變得更有條理一些。