news 2026/11/5 11:10:42

零依赖纯文本知识库:用文件夹+Git搭建永不过期的个人笔记系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
零依赖纯文本知识库:用文件夹+Git搭建永不过期的个人笔记系统

caveman 是我最近一直挂在嘴边的一个小项目代号,外号叫“穴居人方案”。圈子里偶尔看到叫 caveman 的工具或开源项目,思路大多差不多:把知识管理这件事打回原形,不用花哨的 App,不用云端数据库,就用文件夹、纯文本和几个简单脚本,搭一套能扛十年、完全属于你自己的资料系统。我花了一个周末从零把它跑起来,随后连续用了一个季度,今天把整套过程和踩过的坑都摊开讲一遍。

这个方案解决的核心问题是:笔记类工具越做越重,数据锁在别人平台上,本地不想装全家桶,又希望所有内容能长期保存、随时检索、可自动备份。如果你也受够了各种“笔记软件全家桶”,或者对隐私和长期可迁移性有执念,那按下面这套流程走下来,你会得到一个只属于你的纯文本知识库,整个过程大概只要一个小时。

1. 为什么我会做“穴居人”这套东西

1.1 现代知识管理工具的普遍痛点

大概三年前,我还在老老实实用商业笔记软件。一开始体验确实好:界面好看、多端同步、文件夹随便建。但用得越久,问题越明显。最难受的是数据锁死。某天想把笔记批量导出,发现只能按册导出成 HTML 或者它自己的格式,想迁移到别的工具几乎等于重新整理一遍。更别说离线访问要单独装客户端,后台动不动要登录,隐私上心里那道坎一直过不去。

后来我切换成了所谓“第二大脑”类工具,数据库本地存、也有一些开放性。但这类工具的问题在于太重。打开一个界面要等半天,写一条临时想法要经过一堆概念和流程插槽,等你想从里面找一个半年前随手记的灵感时,反而比用文件系统的搜索还麻烦。对我这种技术背景的人,它把简单的事情复杂化了。

于是我开始反思:知识管理最本质的需求其实只有三个。第一,能快速记录;第二,能快速找到;第三,资料不会丢。这三个需求,其实 1970 年代的设计就解决了,就是文件系统、纯文本和版本管理。我把这个思路戏称为“穴居人思维”:不追求花哨工具,像穴居人一样用最原始、最可靠的东西,反而是最耐用的方案。

1.2 为什么是“caveman”而不是某个商业软件

“caveman”这个词听起来糙,但恰好说明了这套方案的核心精神。穴居人不会担心自己的火种被某个平台停服,不会被“云同步”绑架。一个文件夹在手,所有数据都是你的;一个 Git 仓库在手,所有历史版本都是你的;一个 grep 在手,所有内容都能被搜到。

这个方案不是为了否定现代工具,而是为了找回简单可控的感觉。每个文件都是标准 Markdown 纯文本,没有私有格式,任何设备、任何系统打开都不会乱码。文件夹的结构就是分类体系,你可以按自己的习惯建立层级,不用学习软件的“自定义标签”“双向链接”“数据库视图”这些概念。它是反对工具崇拜的:工具越通用,越经得起时间考验;方案越简单,越难出故障。

这个思路适合什么样的人?技术从业者、插件控、隐私敏感用户、长期写作者、自建博客玩家,以及所有被商业笔记软件坑过的人。它不适合需要多人实时协同、离不开富文本排版、或者图片素材特别多还需要在线管理的人。认清这个边界很重要,后面很多问题其实都是边界问题。

2. 核心设计思路:把文件夹当数据库用

2.1 用目录结构代替数据库表

caveman 的设计起点非常朴素:把你的笔记库想象成一台文件柜,而不是一个数据库。这台文件柜只需要几个抽屉。

~/caveman/ ├── daily/ # 日记和日志,按日期命名 ├── notes/ # 常青笔记,主题性内容 ├── inbox/ # 临时想法收集箱 ├── assets/ # 图片、PDF等附件 └── README.md # 使用说明和索引文件

为什么用这四个目录而不是更多?因为需求膨胀会拖垮维护意愿。daily 放时间流内容,notes 放主题性内容,inbox 是应急口,assets 放二进制文件。如果分类太多,记录一个东西前要纠结“该放哪”,几次下来就不想用了。四个目录意味着十五条规则,足够覆盖我百分之九十九的使用场景。

目录里所有的记录都是用日期加短标题作为文件名。例如2024-07-09-搭建博客的流程.md或notes/nginx-cool-timeout.md。日期前缀带来了几个意想不到的好处:文件在系统层面天然按时间排序;重名概率极低;文件名本身就是元数据,不需要特地在正文维护写作时间。标题要是没有,就写untitled.md,记下来再说,内容永远优先于分类。

2.2 纯文本格式与 front matter 的必要性

正文一律用 Markdown 纯文本,不引入任何私有格式。有人会问,要不要像某些工具那样在每个文件头部写 YAML front matter(就是三横线夹着title、tags、date那种)?我的经验是:可以,但能少就少。因为我经常用手机或其他脚本直接读取文件,头部信息越少越不容易出错。

我最终只保留了一个可选字段:tags。其他信息都交给文件名、目录层级和 Git 提交历史去承担,因为这三样东西本身就足够可靠。比如正文首行标题就是索引标题,不需要在 front matter 里重复维护一份。如果你想加标签,写在文件头部或者直接写成内联#标签都可以,检索的时候统一用rg去匹配。

这里有个生活化类比:文件系统是最原始的“图数据库”——目录是父子关系,发往同一处的文件可以互相同步,全文搜索是即时索引。你不需要提前设计复杂的表结构,文件本身就是行,目录树本身就是索引,搜索就是全表扫描。数据量只有几万个文件时,全表扫描完全够快,真的不用焦虑性能问题。真到了那个规模,你盘一下自己的十年笔记量,就会发现这完全不是瓶颈。

2.3 为什么我坚持不用数据库和云服务

caveman 最核心的设计判断,就是不引入数据库、不把数据托付给第三方云服务。原因有三层。

第一,数据所有权。数据库的底层是特权格式,换工具等于转换数据。而纯文本文件夹只依赖操作系统和文件编码标准,这些基础技术不会被某一家公司淘汰。第二,可组合性。文件可以被任何工具读写,Git 可以做历史版本,rsync 可以做备份,SSH 可以远程访问,甚至以后你不想用我的脚本了,自己拿文件管理器操作都可以。第三,故障排查难度低。数据库出问题很难修,文件系统出问题可以用基础工具和备份恢复。方案越是依赖简单的机制,系统崩溃时你需要的救生员越少。

当然,这不意味着与云完全绝缘。我依然用 Git 实现异地备份,把它推到一个私有远程仓库,用 GitHub 或任何你喜欢平台都可以。但这里的逻辑不同:云只是备份存储介质,不是数据的法定监护人。真出事的时候我不需要从某个平台“导出”,只需要git pull就能拿到完整的历史记录。这是一个巨大的心理差别,也是这个方案真正让人安心的地方。

2.4 三个核心命令:尽力避免发明轮子

caveman 没有做成一个庞大的软件,核心就是三个 shell 脚本,或者三个函数:caveman_new(新建笔记)、caveman_find(搜索打开)、caveman_sync(同步备份)。我把它们封装成 Bash 函数,放在~/.bashrc或~/.zshrc里,全 shell 通用,零依赖的情况下也能退化成find加grep。

为什么只做这三个?因为一条知识从产生到复用的闭环就是:记录 → 找到 → 备份。任何编辑、阅读、发布、统计功能都可以用现成工具挂接上去,不必为每个功能自己造轮子。交互形态上,我刻意没有做图形界面,直接用终端和快捷键,因为快是工具的第一美德。

插一句,很多人会觉得脚本方案“简陋”,不如图形软件美观。但美观应该建立在数据组织方式上,而不是皮肤上。我的数据是开放格式,今天用命令行,明天如果觉得不舒服,写个 Web 界面套在这些文件上也就是半个晚上的事情。底层稳了,上层随便换,这种架构上的灵活性,封闭生态给不了。

3. 从零把 caveman 跑起来:完整实操流程

3.1 初始化仓库:十分钟搭好底子

下面这套流程,是在 macOS 和 Linux 上都验证过的,Windows 用户可以用 WSL 或用 Git Bash 模拟。第一步,在用户目录下创建项目文件夹并初始化 Git 仓库:

mkdir -p ~/caveman/{daily,notes,inbox,assets} cd ~/caveman git init echo "# Caveman" > README.md git add . git commit -m "init"

这个过程做了几件重要的事:mkdir创建四个顶级目录;git init让整个笔记库从此有了历史版本管理;README.md作为知识库的“引导页”,我会在顶上写一句话提示自己“先搜再写、先记再理”。顺手git commit保证初始状态干净。

这里你可能会问,为什么assets目录也要纳入 Git 管理?如果一个笔记里的配图只在本地,备份的时候就会缺块。所以要把二进制文件一起放进去。真正的大文件另说,后面会有归档策略。初始化完成之后,你已经有了一台空白的“穴居人知识库”数据目录,接下来给它装上记录入口。

3.2caveman_new:建立新笔记的正确姿势

新笔记的入口脚本,核心逻辑是:生成日期前缀文件名,创建空内容,然后自动打开编辑器。我在~/.bashrc里加了这样一段函数:

caveman_new() { local dir="$HOME/caveman" local date=$(date +%Y-%m-%d) local title="${1:-untitled}" local slug=$(echo "$title" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-') local file="$dir/notes/${date}-${slug}.md" if [ -e "$file" ]; then file="$dir/notes/${date}-${slug}-$$.md" fi if [ ! -f "$file" ]; then touch "$file" fi ${EDITOR:-vim} "$file" }

使用方式就是caveman_new 我的新想法,它会自动落到notes/2024-07-09-我的新想法.md,并打开 vim。如果你只想快速记一句临时内容,用caveman_new tmp然后写几行就行,文件名不完美没关系,以后可以用mv改。

这段代码里有一个细节:tr -cd 'a-z0-9-'是为了剔除文件名里的特殊字符。我踩过名字里带斜杠、冒号的坑,会造成目录层级错乱或者 Windows 不兼容。虽然 UTF-8 和中文系统下中文文件名没问题,但为了跨设备稳定,我还是把文件名的主体转成英文短横连接形式。正文里的标题随便中文,文件名只负责唯一性和排序,这样检索和迁移都非常省心。

3.3caveman_find:秒级全文定位

记录只是开始,更关键的是找到。我在所有依赖都安装的环境下用的方案是基于fd+fzf,这两个工具分别负责快速发现文件和模糊搜索:

caveman_find() { local file file=$(fd . "$HOME/caveman" -e md -e txt | fzf --preview 'bat --style=numbers --color=always {} 2>/dev/null || cat {}') [ -n "$file" ] && ${EDITOR:-vim} "$file" }

fd的作用是快速把所有 Markdown 文档路径列出来,fzf提供一个交互式模糊匹配窗口,文件的同时会实时预览。选中的文件直接用$EDITOR打开。如果想按内容搜关键词,再加一层管道:

caveman_grep() { rg --color always -l "$1" "$HOME/caveman" -g '*.md' | fzf }

这一条命令会先全文搜索出包含关键词的文件列表,再进入 fzf 选择。纯文本的好处在这类场景里特别明显,数据散落在不同目录也不怕,把搜索范围统一指向整个知识库根目录就行。

如果没装 fd/fzf,完全可以用系统自带的find和grep替代。只要你愿意,用文件管理器的搜索框一样能搜到。所谓方案稳定,说的就是即使工具链退化到原始状态,核心流程也不会瘫痪。

3.4caveman_sync:自动备份与多机同步

数据安全靠的是备份意识,自动化让对象永远不用想起它。sync 脚本的职责只有两件事:把本地修改提交到 Git 仓库,再把远程仓库的最新状态拉下来合体。这是我在.bashrc里的版本:

caveman_sync() { cd "$HOME/caveman" || return git pull --rebase --autostash git add -A git commit -m "sync on $(date '+%Y-%m-%d %H:%M:%S')" --allow-empty git push }

这段脚本的思路是:先拉去远端最新内容并自动变基,把本地有而远端没有的改动临时藏起来,New 调整之后再释放。在大多数单机使用场景下,这个流程足够保证两台设备之间不产生严重冲突。--allow-empty保证即使没有任何修改也要建立新的 commit,这样每次同步都会留下一个时间戳,复盘写到哪一阶段更容易。

有人问为什么不挂 cron 定时跑?我两个方式都试过。定时同步适合固定设备,比如家里台式机;但笔记本经常睡眠,网络也不稳定,定时任务经常错过或者报错。最终我保持手动 sync 加上事后几分钟补跑的习惯,偶尔忘记了,下一次 push 会把历史补齐,不会丢内容。关键的教训是:同步不等于备份,三个月至少把一个完整 Git 仓库打包放到外部硬盘或对象存储一次,这才是保底的备份方案。

3.5 可选的发布能力:一键生成静态站点

纯文本的最后一块拼图是发布分享。有时候我希望把一些笔记公开成网页,给朋友看或者自己远端访问。caveman 这次也顺便做了一个 30 行左右的 Python 小工具,把所有 Markdown 转成单个静态 HTML 目录,整个网站所有页面都是相互链接的。

核心流程:用 Python 的markdown库把.md转成 HTML 片段,再套进一个简单模板(含导航、时间、标题),输出到~/caveman/site/。然后我用 Git 或 rsync 把这个site/目录推到多个托管平台。这种方法把“笔记库”和“博客发布”合并成同一个知识库,写完即发布,不需要 CMS 后台。

当然,纯手工用pandoc也一样可以:pandoc file.md -s -o file.html。只是成批转换还是脚本方便。这部分是锦上添花,没有它不影响核心闭环。

4. 一路踩过来的坑:常见问题与排查实录

4.1 中文文件名与编码问题

纯文本方案最怕的就是字符编码和文件系统兼容性。我一开始新文件名直接用中文标题,当时在 macOS 没问题,但同步到旧设备时出现乱码;Windows 上甚至有些字符直接被拒绝作为文件名。最终的处理方案正如上文说的:文件名只用英文短横格式,正文标题保留中文。如果搜不到、找错了文件,第一反应先查看编码,统一文件编码和换行符为 UTF-8 与 LF。

在 Git 层面,可以设置git config core.quotepath false,这样 git status/commit 记录能看到中文文件名,而不是转义成\xxx的形式。别小看它,排查问题的时候看到可读的文件名比看编码要快得多。

4.2 移动端怎么处理

caveman 最弱的一环是手机。因为整个库是文件夹结构,手机上的文件 App 虽然能浏览和编辑,但体验不如原生笔记软件。我的解决方案是折中:手机上放一个只看不写的目录,用 Syncthing 之类的文件同步工具把整个知识库同步过去;偶尔有必须记录的内容,先写到手机里的一个inbox/便捷记录.txt,回家跑一次caveman_sync,再手动归位。对技术人来说这个闭环完全可以接受。

如果你真的需要在线编辑,也可以把整个 Git 仓库推到一个私有仓库,手机上用支持 Git 的编辑器改完再提交。但我不推荐作为主流程,因为移动端输入效率低,重内容还是要在电脑上沉淀。

4.3 文件数量大了会不会卡

我目前的知识库接近两千个 Markdown 文件,fd和rg的响应都在毫秒级。按每天两篇算,十年也才六七千文件,性能压力不大。真正让我卡的是把大量图片也塞进了 Git 仓库,一个几十 MB 二进制文件就会拖慢 pull/push。处理方法很简单:assets里只保存小图,大文件丢到网盘或对象存储,单独在 README 里留链接和说明。

如果未来真的到了上万文件级别,不需要重构整个方案,只需要按年份归档:notes/2024/、notes/2025/,搜索时带时间范围即可。文件系统的弹性往往超出想象,系统瓶颈不在文件数,而在你检索的时候有没有准确的关键词。这时候长期精心写文件名和正文首行就显得特别值钱。

4.4 Git 冲突和误删恢复

用 Git 做同步,不可避免会遇到冲突。虽然--rebase --autostash让大部分场景自动完成,但真冲突来的时候,还是要在终端处理。我自己的经验:冲突往往发生在同一文件在桌面包和笔记本上都有改动的情况。解决方案是避免“同一时段双端同时改同一个文件”,实在不行打开冲突标记手动选择内容。

误删文件是最常见的事故。好在我每次 sync 都 commit,恢复只需要一行代码:

git log --oneline --all -- <被删文件路径> git checkout <commit-hash> -- <被删文件路径>

比起任何笔记软件自带的“删除备份”,这种版本管理语境下的恢复操作永远可用,哪怕文件已经被删三个月,只要 commit 还在就能找回来。这也是纯文本方案最值得宣传的福利之一。

4.5 编辑器与换行的统一

打包前最后一个坑:跨平台的换行符和编辑器差异。Windows 的记事本会默认用 CRLF,导致 Git 提示文件被修改,甚至造成渲染异常。我的解决方案是全局统一:git config core.autocrlf input。编辑器统一用 vim/neovim 或者星门编辑器(VS Code),保存时强制启用 “End with newline” 和 “Trim Trailing White Space”,这能让 diff 和全文搜索少一堆噪音。

4.6 问题速查表

问题现象可能原因解决方案
文件名乱码文件名非 UTF-8文件名统一英文短横,设置core.quotepath false
手机端打不开/不便编辑文件数多,工具慢手机用同步工具,不在此端创作
Git 大量文件冲突双端同改一文件避免双端同时编辑,手动解决少量冲突即可
push/pull 很慢仓库塞了大二进制大文件移出 Git 仓库,用外链引用
搜索到文件但打开失败编辑器路径或默认设置错误检查$EDITOR环境变量,确认文件路径在本地存在
同步时发生 rebase 错误本地有未提交改动先git stash或手动提交,再 pull 后处理

这个速查表是我实际使用中的经验浓缩,比任何文档都管用。如果你是自己的方案,建议同样维护一份自己的速查单,随手记下踩过的坑,回头翻很值得。

5. 使用一个季度后,我对 caveman 的真实体会与扩展方向

真正上手用了一百天后,我的感受可以浓缩成三点。第一,检索变成了一种乐趣。任何时候想找一个半年前的灵感,终端里caveman_find然后敲几个关键词,几乎零等待。过去我用图形笔记软件想搜一个笔记,要先等客户端加载,再看着转圈,像开盲盒一样。第二,写作的摩擦被降到最低。起个文件名,打开 vim,正文直接敲,没有字体弹窗,没有排版工具栏,让我非常专注于内容本身。第三,心里踏实。所有数据躺在本地,备份一次就是 git push,十年后平台还在不在未知,但我这些.md文件比我存过的大部分云盘活得都长。

当然它也不完美。多人协同场景完全没有,富文本、表格、日历视图也不存在,连手机端都只能勉强看和轻量改。这个方案的代价是把很多需求和审美转移到自己的知识和脚本里,如果你是团队协作型选手,它并不合用。但如果是个人知识管理,这套方案的收益远大于代价。

后续扩展的方向我列在下面,读者可以按自己的需求挂接。

  • 日记模板:caveman_new daily支持生成当天日记的模板(天气、心情、三件要事),文件落到daily/2024-07-09.md。
  • 书摘和链接库:每条资料存一个notes/book-书名.md,头部写书籍元数据,正文放摘抄、评论、引用链接。
  • 记账:用 TSV 文件存记账记录,配合 Unix 工具做月度汇总。这不是 Excel 的平替,但秒开秒查。
  • 发布博客:使用前文提到的静态站点生成脚本,把notes中带public标签的笔记发布成站点。
  • 任务管理:把任务文件丢进inbox,每天写下“今天要做的”,用待办勾选语法标记。

我个人在实际操作中的一个小小体会是:不要一上来就把自己这套方案设计成一个大平台。从一个目录、一个脚本开始,用一周记录自己的想法,再逐步加功能。等用顺手了,工具和方法论会自然长成你自己的形状。最稳定的系统不是我写的代码,而是这个习惯本身——不管工具多简陋,只要你肯打开它写几行字,它就是最好用的工具。

最后想给大家一句忠告:方案的核心不是技术,而是你对资料的长期主义。穴居人方案的魅力不在脚本,在于把复杂归还给简单,把数据交还给你自己。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/23 4:47:41

学习通刷课脚本全解析:Selenium自动化播放与FontTools字体解密实战

简介&#xff1a;一套基于 Python 的学习通自动刷课脚本源码&#xff0c;面向希望借助自动化完成平台课程任务、减少重复点击的学习者&#xff0c;也适合想在 Selenium 浏览器操作和 fonttools 字体处理上做实践参考的 Python 开发者。资源包共 27 个文件、约 2.41MB&#xff0…

作者头像 李华
网站建设 2026/11/4 22:17:19

Claude Code学术研究技能包ARS:论文写作全流程的LaTeX配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/23 10:07:33

BqLog高性能日志原理:环形队列与自适应数据总线解析

1. 为什么BqLog的日志吞吐能稳压20万条/秒&#xff1f;先拆开它的“心脏”看一眼你有没有试过在王者荣耀这种峰值QPS超百万的实时对战场景里&#xff0c;给每个英雄技能释放、伤害计算、网络同步都打上完整日志&#xff1f;我去年在某一线游戏SDK团队做性能审计时&#xff0c;亲…

作者头像 李华