ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

用Bash打造极简命令行工具caveman:纯文本效率管理实践

用Bash打造极简命令行工具caveman:纯文本效率管理实践 说实话我第一次看到 “caveman” 这个词脑子里冒出来的是老动画片里穿兽皮、举石头的穴居人形象。但把它当成一个项目名来认真琢磨是另外一回事。我越来越觉得现在的人缺的不是更好用的软件而是像穴居人一样“只用必要的东西解决问题”的本能。那段时间我手机里堆了十几个效率 App待办用一个软件笔记用一个软件工时记录再用一个习惯打卡又换一个。表面上看各司其职实际上我得记住每个 App 的入口、同步逻辑和订阅状态还要不停应付更新弹窗。真正被消耗掉的不是时间而是专注力。于是我开始想如果我像穴居人一样只保留最原始、最可靠的一套工具生活会变成什么样这个念头最终变成了一个叫 caveman 的命令行项目。这篇文章会把它是什么、为什么这么做、怎么落地、踩过哪些坑全部摊开来讲。1. 从 caveman 这个词开始为什么我要给自己造一个“原始人工具箱”先解释一下 caveman 这个名字。它直译是“穴居人”放在项目语境里代表一种刻意后退的姿态我不追求图形界面、云端同步、人工智能推荐只追求“一个命令能干完的事绝不用十个按钮完成”。我把这个极简命令行工具命名为 caveman就是在提醒自己——别把简单的事搞复杂。我的核心痛点非常具体每天要快速记下一件事要知道自己还有哪些事没做完要能隔一段时间复盘还要保证数据永远属于自己、不依赖任何服务器。市面上的工具没有一个能同时满足这四点。大多数 App 做的是“管理任务”而不是“帮助你完成任务”它们的核心商业模式是让你持续打开它而不是让你尽快关掉它。这种体验久了真的很累。于是我用大概一个周末用纯 Bash 写了一套工具。它能做四件事待办清单、快速笔记、时间追踪、每日回顾。所有数据以纯文本形式放在用户目录的.caveman文件夹里删掉工具本体数据也不会受影响。它没有数据库没有网络请求没有后台进程甚至连配置文件都只有一个环境变量。听起来像开玩笑但实际用下来它比我之前所有“强大”的效率工具都更稳定。1.1 现代工具的复杂度焦虑我不否认复杂工具的价值但复杂工具的成本经常被低估。一个任务管理软件如果有一百个功能你就得花时间学会其中九十多个用不上的功能它的更新会改变操作位置它的订阅会到期它的云同步偶尔会冲突。这些成本会在某个时刻超过它带来的收益只是很多人没意识到。我自己的崩溃时刻是某天晚上我花了二十分钟在工具里把任务打上标签、设置优先级、拖拽排序结果真正要做的三件事一件都没开始。那一刻我觉得特别荒谬。后来我就想穴居人安排一天根本不需要标签系统——他只需要知道“今天要打猎”和“猎物还没打到”。这个朴素逻辑其实就是 caveman 项目的出发点。1.2 caveman 不是什么万能药必须老实说caveman 不适合所有人。它没有手机推送没有团队协作没有甘特图没有漂亮的图表报告。如果你需要这些功能强烈建议继续用专业工具不要硬折腾。它适合的是另一类人工作在终端里进行的技术人员、写作者、对数据掌控有强需求的人以及所有对“工具越多越焦虑”深有体会的人。核心价值不是功能全面而是让你重新拿回对工具和数据的主控权。对我来说它就像一块燧石——谈不上精致但任何时候敲一敲都能出火。2. 设计与选型为什么“最原始”的方案反而最可靠这个项目里最值得讲的不是功能而是设计取舍。我在做之前列了几个硬性要求每个都排除了不少“更现代”的技术方案。首先整个工具必须是单文件。不是微服务不是插件化架构就是一个几百行的 Bash 脚本。其次数据必须是纯文本不能用 SQLite不能用 JSON 二进制序列化更不能存在某个公司的服务器上。最后脚本本身的复杂度必须控制在“任何人两小时内能读懂”的范围内。这些要求决定了后续所有技术选型。2.1 数据比工具重要纯文本的长期主义为什么如此执着于纯文本因为工具会死数据不会。任何一个软件都可能停止维护但一个按行排列的文本文件三十年后照样能用记事本打开。纯文本还意味着所有 Unix 生态的工具都能直接处理它grep搜索、cat拼接、wc统计、awk分析、git做版本管理不需要额外的库或驱动。举个例子我想知道某一天的笔记里总共写了多少字一句wc -l就出来了我想统计某个项目在时间追踪里出现了几次一句grep -c 项目名 timer.log就搞定。这种自由度是任何封闭软件都给不了的。更重要的是当我想换工具时不需要做“数据迁移”——文本本身就是迁移格式。2.2 为什么不是 Python 或 Go有人可能会问写命令行工具用 Python 不是更简单吗确实是更简单但这里有个权衡。Bash 是几乎所有 Unix 系统的默认组件不需要安装解释器不需要虚拟环境也不需要处理依赖版本。我把脚本扔到任何一台 Linux 或 macOS 机器上挂到 PATH 里就能运行。这一点对“随时随地可复现”的项目精神来说太重要了。Bash 的缺点是逻辑复杂后容易写出隐蔽的 bug尤其是各种引号展开和分词陷阱。我控制项目规模的方式是“功能瘦身”只保留四类子命令每个子命令只支持四五个参数。如果某个需求让脚本超过三百行我就重新思考这个需求是不是必要的。这种约束反而逼着我把功能设计得足够聚焦。2.3 数据目录怎么组织按“日子”而不是按“项目”caveman 的数据目录长这样~/.caveman/ ├── todo.txt ├── notes/ │ └── 2025-03-01.md │ └── 2025-03-02.md ├── timer.log └── journal/ └── 2025-03.md设计考量很直白对个人效率管理来说“今天”是最高频的天然单位按日期归档可以避免分类焦虑。很多人用笔记软件时最大的问题是建了二十个文件夹却不知道该把一条随手记放哪里。caveman 干脆取消了这个选择一切按日期走如果以后想按主题整理用grep就能从所有文件里捞出来。todo.txt是唯一没有按日期拆分的文件因为任务天然具有跨日属性。它保存的是当前所有未完成和已完成任务的文本流每行一条。timer.log则是纯追加的时间流水方便做周报时用awk按列汇总。3. 从零到一caveman 的完整实现下面进入实操环节。我不打算贴一个五百行的完整脚本那样太啰嗦而且每个人的需求不同。我更想把骨架和几个关键函数的实现思路讲透让读者能照着搭出适合自己的版本。3.1 脚本入口与命令分发整个工具的本质是一个带子命令的脚本。入口用 Bash 的case分发结构清晰后续加子命令也容易。开头先定义数据目录和几个关键变量#!/usr/bin/env bash set -euo pipefail CAVE_ROOT${CAVE_ROOT:-$HOME/.caveman} CAVE_NOTE_DIR$CAVE_ROOT/notes CAVE_TODO$CAVE_ROOT/todo.txt CAVE_TIMER$CAVE_ROOT/timer.log CAVE_JOURNAL$CAVE_ROOT/journal mkdir -p $CAVE_NOTE_DIR $CAVE_JOURNALset -euo pipefail这三行非常关键建议所有 Bash 脚本都写上。-e让脚本在出错时立即退出避免带着错误状态继续跑-u让未定义变量的引用直接报错能揪出很多手滑写错的变量名pipefail让管道中任意一环失败时整体返回失败而不是只看最后一条命令的退出码。没有这三行Bash 写起来会非常“飘”出了错都不知道在哪。分发部分长这样cmd${1:-help} case $cmd in todo) shift; cmd_todo $ ;; note) shift; cmd_note $ ;; timer) shift; cmd_timer $ ;; log) shift; cmd_log $ ;; *) help ;; esac注意我用了shift把子命令本身从参数列表里去掉这样每个cmd_*函数拿到的$就是纯粹的子参数。这种写法比在每个函数里再判断$1是子命令序号干净很多。3.2 待办功能caveman todo待办可能是最常用也最核心的模块。我的设计是用行首的[ ]和[x]标记区分未完成和已完成而不是一做完就删除。这样保留了一条任务从出生到完成的完整历史方便后续复盘。cmd_todo() { touch $CAVE_TODO action${1:-list} shift || true case $action in add) echo [ ] $(date %Y-%m-%d %H:%M) $* $CAVE_TODO ;; list) grep -n ^\[ \] $CAVE_TODO ;; done) sed -i.bak ${1}s/^\[ \]/[x]/ $CAVE_TODO ;; clean) $CAVE_TODO ;; esac }有几个细节想特别解释。sed -i.bak是跨平台兼容的做法macOS 的sed在-i后必须跟扩展名参数否则会报错Linux 上sed -i可以直接用。统一写成sed -i.bak两边都能跑代价是每次会留下一个.bak备份文件定期删掉就行。更优雅的做法是检测系统类型动态设置参数但对个人项目来说没必要那么讲究。grep -n ^\[ \]会输出“真实行号 任务文本”比如3:[ ] 2025-03-01 14:32 写周报。这个行号是文件里的真实行号所以后续执行caveman todo done 3时sed修改的也是文件的第 3 行。这个细节很关键否则你看到的“序号”和文件实际行号一旦对不上就会误改任务。我刻意没有做优先级、截止日期、标签这些功能。原因很朴素任务管理的核心动作是“完成”不是“排序”。如果一天的任务多到必须用优先级排序说明不是工具的问题是任务的节奏出了问题。3.3 快速笔记caveman note笔记模块的设计目标是“零成本记录”不需要选分类不需要建标题只需要一句话。实现上我让每条笔记追加到当天的 markdown 文件里用时间作为小节标题cmd_note() { f$CAVE_NOTE_DIR/$(date %Y-%m-%d).md if [ ${1:-} open ]; then ${EDITOR:-vim} $f else printf \n## %s\n%s\n $(date %H:%M) $* $f fi }使用效果是这样的在终端里输入caveman note 修复了登录模块的缓存问题脚本就把这条内容写进notes/2025-03-01.md并在前面自动加一个时间戳标题。三秒钟完成不需要切换窗口不需要思考“该放哪个文件夹”。想展开写就去敲caveman note open它会直接用$EDITOR打开当天的文件。这种做法对“灵感捕获”特别有效。我过去用笔记软件时很多一闪而过的想法会因为“懒得分类”而丢掉caveman 把这个摩擦成本降到了接近于零。3.4 时间追踪caveman timer我每周都有统计各类工作耗时的需求所以写了 timer 模块。它的数据格式是 TSVTab 分隔值每行三列开始时间戳、结束时间戳、任务名称。当一个任务开始时写入一条只有开始时间戳和名称的记录结束时再回来补上结束时间戳。核心逻辑是把时间戳存成 Unix 秒数这样算时长就是简单的减法再自己换算成小时分钟cmd_timer() { action${1:-status} case $action in start) printf %s\t%s\n $(date %s) $* $CAVE_TIMER ;; stop) end$(date %s) # 取最后一行未闭合的记录补上结束时间 awk -v end$end /^[0-9]\t/ !/^[0-9]\t[0-9]\t/ { $0 $0 end; # 简化示意实际要对列插入 } { print } $CAVE_TIMER $CAVE_TIMER.tmp mv $CAVE_TIMER.tmp $CAVE_TIMER ;; esac }上面的 awk 片段是示意性的真正写的时候需要处理 Tab 列的插入。我在自己的版本里其实是直接用最后一行替换逻辑更简单。这里更值得记的是设计教训如果你对 awk 和 sed 不够熟不要在时间追踪这种需要精确改行的逻辑里硬写更稳的方案是把每次 start 和 stop 都追加成独立行后面统计时用配对算法处理。虽然文件会变长几十倍但对个人项目来说完全不是问题。3.5 每日回顾caveman loglog 模块是我最喜欢的部分。它不做复杂加工只是把一天散落在各处的记录聚合到一个视图里cmd_log() { d${1:-$(date %Y-%m-%d)} echo Todo grep $d $CAVE_TODO || true echo Notes cat $CAVE_NOTE_DIR/$d.md 2/dev/null || echo (无笔记) echo Timer grep -E $d $CAVE_TIMER || echo (无计时记录) }每天晚上花三分钟浏览这些内容就能清晰地看到今天完成了什么、卡在哪里、时间花到了什么地方。这个回顾习惯比任何自动生成的统计数据都有用因为数据是最原始的第一手记录没有经过工具算法的“加工”。4. 实际使用我的一天是怎么被 caveman 安排的项目做出来是一回事真正让我坚持用的是它能融进日常生活。下面是我比较典型的一天的用法。4.1 早晨 5 分钟规划早上打开终端第一件事是执行caveman todo list看看有哪些任务从昨天留下来了。然后我会挑出今天最重要的一件事把它作为第一条加入待办caveman todo add 完成产品方案初稿。这样整个列表顶部就是今日主轴往下才是其他次要事项。选择在终端而不是手机 App 里做规划看起来不太“现代”但有一个非常实际的好处终端里没有通知没有红点没有推送。你打开它就只能看到任务本身不会被其他东西带偏。4.2 写代码时的随手记录开发过程里最怕的是思路中断。以前遇到一个临时问题我会切到浏览器去搜索或记下来结果往往是切出去就回不来了。现在我只敲一行命令caveman note 发现订单模块的金额计算精度有问题明天处理。内容落盘后大脑从“保持记忆的紧张感”里解脱出来可以立刻回到当下的编码工作里。4.3 晚上的回顾与归档晚上我会执行caveman log把当天所有记录过一遍。看到未完成的任务我会评估一下如果明天还值得做就再caveman todo add一遍如果不值得直接让它留在历史里就好。这个“二次过滤”很重要因为不是所有当时觉得重要的事回头都真的重要。之后我会把当天的笔记整理一下长文展开可以在caveman note open里补零散话术则保持原样。这个过程不是强制任务而是顺手做的三分钟小事。4.4 多设备同步git 就够了caveman 本身没有同步功能但纯文本数据给了我最简单的同步方案Git。在~/.caveman目录里执行git init然后把目录推到私有仓库换设备或重装系统后git clone回来即可。因为文件全是文本git diff能看到每天到底改了哪些内容任务历史天然可追溯。我还会在系统里配一个定时任务每半小时自动执行git add -A git commit -m auto这样连手动同步都省了。这个方案没有任何锁冲突和同步失败的问题因为文本文件的冲突合并几乎总是容易处理。唯一要提醒的是私有仓库的访问凭据不要硬编码在脚本里要使用系统凭据管理器避免把密钥写进明文脚本。5. 常见问题与排查实录任何工具用久了都会遇到问题。下面是我在开发和使用 caveman 过程中真实踩过的坑整理成一个速查表供读者参考。5.1 脚本没权限或找不到命令刚写完脚本时总是遇到command not found。原因无非两个文件没有可执行权限或者脚本所在目录不在PATH里。解决办法是执行chmod x caveman然后把脚本放到/usr/local/bin或者~/bin并确认PATH里包含对应目录。用echo $PATH检查一下一目了然。5.2 参数里有空格、引号和特殊符号这是 Bash 新手最容易踩的坑。假设要添加的任务包含空格caveman todo add 周三 10:00 开会Shell 会把这个命令拆成 5 个参数最后保存的内容可能变成周三 10:00 开会——恰好没问题但如果参数里有需要保留的空格比如caveman note add 记得买 牛奶和鸡蛋就可能被错误拆分。解决方法是始终用引号包住参数caveman todo add 周三 10:00 开会。在脚本内部对应地使用$而不是$*来保留每个参数的边界。这也是我在代码里反复强调的地方凡是拿不准的地方加引号没坏处。5.3 done 和 delete 的行号对不上早期版本里我做了一个“已完成任务过滤后序号”的功能结果任务一旦完成列表序号就会整体前移下一次按序号操作就会改错行。后来改成用grep -n输出真实文件行号才彻底解决这个问题。这里给读者的经验是在 shell 工具里处理“行”时永远让命令直接操作真实行号不要自己在逻辑里维护一套“可见序号”。否则一旦数据有增删两套数字立刻就会错位。5.4 Linux 和 macOS 的 sed 差异同一个sed -i在 Linux 上能用在 macOS 上会报sed: 1: ... : extra characters at the end of c command。因为 BSD 版的sed规定-i后面必须跟后缀参数。我用的兼容写法是sed -i.bak s/^.../.../ 文件这样两个平台都能跑缺点是会生成.bak文件可以在命令后面再补一条rm -f $CAVE_TODO.bak清理掉。5.5 备份与恢复caveman 的备份最简单的方式就是复制目录cp -r ~/.caveman ~/.caveman.backup。因为全是文本整个目录通常只有几百 KB。可以再用crontab定期打包到其他磁盘或者配合 Git 每天提交。恢复就更简单了把备份目录放回去工具直接就能读不需要任何额外初始化。这是纯文本方案最大的红利也是我推荐大家尝试的重要原因。6. 后续还能怎么扩展让这个原始人工具再进化一点caveman 目前的形态已经满足了我的大部分需求但它并不是只能停在这里。我试过几个很实用的扩展方向分享给有兴趣的读者。第一个是把时间追踪的结果汇总成周报。因为timer.log是 TSV 格式用awk按任务名称聚合、按周求和就能输出这周各项目花了多少时间。我最初的实现是每天手动查看后来改成每周五跑一段三行的 awk 脚本效率提升非常明显。第二个是给待办加一个简单的“计划日期”字段。不需要复杂的日历系统只要在任务末尾追加一句on 2025-03-05然后日常用grep过滤出当天和过期的任务即可。这个方案能让你在终端里也获得“今天该做什么”的视图同时保持数据仍然是纯文本。第三个是把系统通知接进来。在 cron 或定时任务里跑一句带notify-send的命令就能在指定时间弹出桌面提醒macOS 上则可以用osascript -e display notification ...实现。这算是给 caveman 补上一个“主动提醒”的能力用最简单的方式覆盖它原本缺失的功能。我自己实际用下来的体会是造这样一个工具最大的收获不是省了多少时间而是重新建立了一种“我的数据我做主”的掌控感。今天很多软件都想把用户留在产品里而 caveman 的理念恰恰相反——它希望你尽快记完、尽快离开、尽快回到真正的生活和工作中去。如果你也厌倦了被工具绑架的感觉可以花一个周末试着给自己写个“穴居人工具”哪怕只有两三个功能用起来也会是完全不同的体验。
返回列表