用 GNU Stow 管理你的 dotfiles 农场
根据 GNU Free Documentation License, 版本 1.3 或 Free Software Foundation 发布的任何后续版本之条款, 无 Invariant Sections, 无 Front-Cover Texts 及无 Back-Cover Texts, 或根据 Creative Commons Attribution-ShareAlike 4.0 International 之条款, 授予复制, 分发和/或修改本文的许可
Stow 最初的用途是管理 /usr/local/ 等目录下通过源代码编译的软件. 它将不同软件包的程序文件安装到独立的目录 (如 /usr/local/stow/emacs/), 通过符号链接将这些文件聚合到公共路径 (如 /usr/local/bin/) 中. 这使得软件包的追踪和管理更加简单, 只需要修改其对应的符号链接即可.
这样的理念同样适用于 dotfiles: 用户可以将文件集中存储, 再由 Stow 将它们链接回原位.
Stow 存在于大多数 GNU/Linux 发行版的软件仓库中. 例如, 在 Arch Linux 上, 使用 pacman 安装:
pacman -S extra/stow
1. 基本概念
Stow 基于一个简单的约定工作: 包目录的目录树镜像目标目录的目录树.
例如, 将 ~/.dotfiles/ 作为 Stow 的根目录, 每个子目录代表一个包:
.dotfiles/
└── bash/
├── .bashrc
└── .config/
└── bash/
└── bashrc
执行 stow bash 时, Stow 会在 ~ 下创建对应的符号链接:
~/
├── .bashrc -> .dotfiles/bash/.bashrc
└── .config/ -> .dotfiles/bash/.config
stow 的默认目标目录是当前目录的父目录. 因此, 在 ~/.dotfiles/ 内执行 stow bash 会以 ~ 为目标创建链接.
使用
-d指定 Stow 目录,-t指定目标目录. 例如:stow -d ~/my-stow-dir -t ~ bash
2. 使用示例
假设我们在 ~/.dotfiles/bash/ 下准备了上述 .bashrc 和 .config/bash/bashrc.
再次执行 stow 时, 使用 -vv 查看状态:
cd ~/.dotfiles
stow -vv bash
Stow 会报告每个文件的状态:
stow dir is ~/.dotfiles
stow dir path relative to target ~ is .dotfiles
Planning stow of: bash ...
Planning stow of package bash...
level of .bashrc is 0
--- Skipping .bashrc as it already points to .dotfiles/bash/.bashrc
level of .config is 0
--- Skipping .config as it already points to .dotfiles/bash/.config
Planning stow of package bash... done
Processing tasks...
-v接受 0-5 级.-v仅在创建或删除链接时有输出;-vv会额外显示已跳过的链接;-vvv展示完整的处理过程.
在修改 dotfiles 后, 已有的符号链接会自动反映更改. 如果包中添加了新文件, 应重新执行 stow:
-R 会先删除旧的符号链接再重新创建, 相当于 stow -D <package> && stow <package>.
stow -R bash
要移除一个包的所有符号链接, 使用 -D:
stow -D bash
3. 常见选项
-n/--no 模拟执行, 将显示将会进行的操作而不进行实际更改. 在对现有配置进行大规模修改前, 推荐先用 -n 检查:
stow -n -R bash
--adopt 将目标目录已有的文件导入至 Stow 包.
例如, 如果 ~/.bashrc 已经存在, --adopt 会将其移动到 Stow 包目录中, 再在原位创建符号链接:
stow --adopt bash
--adopt会覆盖 Stow 包目录中的同名文件.
--no-folding 禁用目录折叠. 上述示例中, Stow 默认将 .config 整个目录链接为单个符号链接. 如果需要在同一目录下混合存放不同包的配置文件, --no-folding 会很有用.
--dotfiles 允许在包目录中使用 dot- 前缀替代 . 前缀.
例如, 将 .bashrc 命名为 dot-bashrc, Stow 链接时会自动将 dot- 转换为 .:
.dotfiles/
└── bash/
└── dot-bashrcstow --dotfiles bash
此时 ~/.bashrc 将链接到 .dotfiles/bash/dot-bashrc.
4. 配置文件
Stow 支持通过配置文件设置默认选项. ~/.stowrc (或项目目录下的 .stowrc) 可以包含任意命令行选项:
# .stowrc
--target ~
--dir ~/.dotfiles
此外, 在每个包目录下放置 .stow-local-ignore 文件, 或在 ~ 下放置 .stow-global-ignore, 使用 Perl 正则排除不需要链接的文件:
# .stow-global-ignore
.git
README.*
*.swp
5. 配合 Git
将 ~/.dotfiles/ 初始化为 Git 仓库并推送到远端, 即可同步 dotfiles:
cd ~/.dotfiles
git init
git remote add origin <remote-url>
git add -A
git commit -m "init: add dotfiles"
git push -u origin main
在新机器上, 克隆仓库并执行 stow:
git clone <remote-url> ~/.dotfiles
cd ~/.dotfiles
stow bash
推荐将
.stow-local-ignore和.stow-global-ignore一并纳入版本控制, 确保不同设备上 stow 的行为一致.
要了解更多关于 Stow 的用法, 参阅 GNU Stow 手册 与 stow(8).