锦方的个人网页 · 如果有一天你突然想起了我


macOS 外置硬盘为什么会出现 ._* 文件

目录

最近我把一个 Zola 网站项目放在外置硬盘上维护。新增几个 Markdown 文件后,项目里同时出现了这些文件:

content/projects/muzhai.md
content/projects/._muzhai.md

真正的项目文件只有 muzhai.md,前面带 ._ 的文件不是我创建的内容,而是 macOS 生成的 AppleDouble 边车文件。

它们通常很小,却可能进入 Git 状态、静态网站构建结果、压缩包或服务器目录。只在 Finder 里工作时不一定会注意到,到了发布检查阶段才容易暴露出来。

._* 文件是什么

macOS 除了保存文件正文,还会使用扩展属性、Finder 信息和资源叉等元数据。APFS 等原生文件系统可以直接保存这些信息;当目标磁盘、网络共享或复制方式不能按原来的形式保存时,macOS 可能把元数据放进一个独立文件。

例如:

image.png
._image.png

image.png 是正常文件,._image.png 是与它配套的 AppleDouble 文件。外置磁盘、非原生文件系统、NAS 和跨系统复制中都可能遇到这种情况。

项目里还可能出现 .DS_Store。它保存 Finder 的目录显示信息,作用和 AppleDouble 不完全相同,但对源码仓库来说通常都属于不应该发布的文件。

为什么会影响 Git 和静态网站

如果只是多出几个隐藏文件,看起来问题不大。但对自动构建来说,它们和普通文件一样真实存在。

可能出现的问题包括:

我这次新增五个项目页面时,外置硬盘就在每个 Markdown 文件旁生成了一个 ._文件名.md。内容校验本身没有错误,但文件系统门禁发现了五个额外文件,因此发布流程被停止。

这正是门禁应该做的事:不要等边车文件已经上传后再处理。

第一步:先列出来,不要直接删除

可以先在项目根目录检查:

find . \
  -path './.git' -prune -o \
  -type f \( -name '.DS_Store' -o -name '._*' -o -name '.__*' \) \
  -print

这里排除了 .git,因为仓库内部可能也有文件系统产生的元数据,但不应该在不理解 Git 目录结构的情况下直接批量处理。

检查结果时要先确认两件事:

  1. 对应的正常文件是否存在。
  2. 当前目录是不是以 Git 中的源码为唯一可信来源。

对于照片库、老磁盘或设计文件目录,不建议看到 ._* 就全部删除。这些文件可能保存原文件系统无法容纳的资源叉或扩展属性,应该先备份并确认用途。

macOS 自带的 dot_clean

macOS 提供了 dot_clean,用于把 ._* 中的信息合并回对应的原文件:

dot_clean /path/to/directory

在执行前可以查看帮助:

man dot_clean

它默认递归处理目录。-m 参数会始终删除 ._* 文件,因此不能在不理解数据的情况下随意使用:

dot_clean -m /path/to/directory

对于普通资料盘,我更倾向于先备份,再使用默认合并方式。对于确认由 Git 管理、边车文件不属于项目内容的源码仓库,则可以使用项目自己的精确清理脚本。

我在 Zola 项目里的处理方式

我没有只做一次手动删除,而是设置了多层防线。

1. Git 忽略

.gitignore 中加入:

.DS_Store
**/.DS_Store
._*
**/._*
**/.__*

这可以降低误提交的风险,但它只影响 Git。文件仍然留在磁盘上,其他构建工具依然可能看到它,所以不能把 .gitignore 当成完整解决方案。

2. Zola 忽略

config.toml 中同时限制内容目录和静态资源目录:

ignored_content = ["**/.DS_Store", "**/._*", "**/.__*"]
ignored_static = ["**/.DS_Store", "**/._*", "**/.__*"]

这样即使边车文件再次出现,Zola 也不应该把它当成文章或公开资源。

如果项目原来还有其他忽略路径,例如私有目录,应在原数组基础上追加规则,不要直接覆盖原有配置。

3. 发布前门禁

项目中的检查脚本会扫描 .git、私有目录和构建目录之外的位置:

./scripts/check-filesystem-metadata.sh

发现文件时只报告路径并返回失败,不会默认删除。这使本地构建和 CI 都能在发布前停下来。

确认列表里的文件都是可再生边车后,再执行:

./scripts/check-filesystem-metadata.sh --clean

清理完成后必须重新检查:

./scripts/check-filesystem-metadata.sh
git status --short
zola check --skip-external-links

4. 构建产物再检查一次

源码目录干净,不代表 public/ 一定干净。发布脚本还应该检查最终生成目录,避免静态资源复制或其他工具重新产生边车文件。

我会把“源码边界”和“公开产物边界”分开检查:

一个更稳妥的发布顺序

现在我在外置硬盘上的 Zola 项目通常按这个顺序处理:

./scripts/check-filesystem-metadata.sh
node scripts/validate-frontmatter.mjs
zola check --skip-external-links
zola build
git status --short

如果第一步失败,先查看文件清单,确认后清理,再从头执行。不要因为已经在 .gitignore 中配置过,就忽略磁盘上实际存在的文件。

总结

._* 并不一定是病毒,也不是项目代码自动生成的缓存。它是 macOS 为兼容不同文件系统和复制方式而使用的元数据边车。

真正的问题不是它出现了,而是源码仓库和发布流程没有明确边界。

对普通磁盘,先备份并理解元数据,再考虑合并或删除;对 Git 管理的源码项目,则应该同时做好 Git 忽略、构建工具忽略、发布前扫描和最终产物检查。这样即使外置硬盘再次生成 AppleDouble 文件,它也会在上传之前被发现。

系列:note

该系列自动来自分类: note

  1. Gemini 3.6 Flash完美弥补了Codex 5.6
  2. macOS 外置硬盘为什么会出现 ._* 文件 (当前)
  3. 小众工具软件应该免费、买断还是订阅
  4. 用iPhone和iPad维护Git静态网站可行吗
  5. 一个Mac截图工具,从能截图到能上架还差多远
  6. 重复文件清理工具最危险的不是漏扫,而是误删
  7. 备份dokuwiki数据
  8. grep 命令
  9. zola的Front Matter完整字段的意思
  10. 从dokuwiki切换到quartz
  11. 安装immich记录
  12. 修改dokuwiki时区
  13. macos安装dokuwiki
  14. Debian创建新用户和设置防火墙
  15. mac在Debian安装wireguard和使用
  16. 再也不买不能解bl的手机了
  17. Firefox设置
  18. debian安装FFmpeg来合并youtube音频
  19. css 扩散列表
  20. 两个练习
  21. css RWD
  22. css 图片
  23. css 提示
  24. css 下拉
  25. css 表单
  26. css 导航栏
  27. css 单词
  28. HTML SVG
  29. HTML Canvas
  30. HTML input
  31. HTML 结构
  32. 电气施工图说明
  33. china uses dropbox
  34. Nginx installs SSL certificates
  35. debian install shadowsocks
  36. Visual studio code set the python environment
  37. install hexo

下一篇推荐

系列继续阅读

小众工具软件应该免费、买断还是订阅