我给自己定过一条规矩:能用命令行完成的事,绝不去开图形窗口。这个习惯慢慢沉淀成了一套方法论,我给它起了个名字叫CLI-Anything。它不是某个特定的开源软件,也不是简历上的炫技项目,而是一整套用命令行解决日常任务的工具组合、脚本片段和操作准则。靠这套东西,我处理几百个文件的整理归档、批量拉接口数据、在几万行日志里定位异常,基本都在一两分钟内完成,而且过程可回放、可复用、可交给机器自动跑。如果你也经常被重复劳动折磨,或者想把手头的工作流彻底改造一遍,这篇文章值得你从头看到尾。下面所有命令我都实际跑过,所有坑都是真金白银踩出来的。
1. 从"图形界面惯性"到"一切皆命令":CLI-Anything到底是什么
1.1 不是某个软件,而是一套操作准则
CLI-Anything 本质上说的是:任何重复发生两次以上的操作,都值得思考一下有没有命令行方案把它自动化。图形界面就像你去银行柜台办业务,流程清晰但每办一笔都要排队、点按钮、等弹窗;命令行则像你写好一张自动化的委托单,机器拿到之后自己执行,不用你一次次重复劳动。
我刚开始尝试的时候也很怀疑,毕竟图形界面看起来更直观,文件夹一目了然,拖拽就能完成操作。但真正让我转变的是一次下载目录整理:五百多个文件,类型五花八门,用鼠标一个个归类差不多得半小时。后来我写了一个不到十行的循环脚本,把同名、同扩展名的文件按类型分进不同目录,整个过程跑完不超过五秒。那一刻我才意识到,"看得见"有时候反而是负担,命令行虽然看不到图形,但它能批量处理、能记录、能复用。
这套准则落到日常里大概包含这么几条:能用管道组合命令解决的,就不写临时脚本;能写成脚本复用的,就不重复敲命令;能被自动化定时执行的,就不手动触发。它不是要求你抛弃所有图形界面,而是要求你在动手之前先想一下"这个动作我会做几遍,一遍和一百遍的成本差多少"。
1.2 命令行"万能"的底层逻辑:组合、脚本、确定性
为什么命令行能做到"Anything"?我总结出三个底层特性。
第一是组合性。命令行工具彼此之间通过标准输入输出衔接,一个命令的输出直接成为另一个命令的输入。这种设计就是"管道",它让简单的工具像乐高积木一样拼出复杂功能。比如我要看当前目录下最大的十个文件,就是ls -lhS | head -10,甚至不用装任何额外工具。每一个单一命令只做一件事,但组合起来就是无穷无尽的可能性。
第二是可脚本化。图形界面操作可以被录制宏,但绝大多数情况下它不能被参数化,不能处理"今天是第 3 页数据、明天是第 8 页数据"这样的变化。命令行则天然支持变量、循环、条件判断。一旦你把命令写进脚本,它就从"你会做"变成了"机器替你做",人只需要处理脚本覆盖不到的异常分支。
第三是确定性。同一个命令在同样的环境下执行,得到的结果是稳定一致的。图形界面操作则受鼠标轨迹、菜单状态、系统弹窗干扰,第一百次点击和第一次点击一样容易误触。对于需要审计、复盘、追溯的任务,命令行天然留下完整记录,你知道每一步发生了什么。
1.3 边界:什么任务不该硬上命令行
CLI-Anything 不是万能神药,硬把所有事情都塞进命令行反而是另一种低效。我自己的判断标准是三个问题:重复几次?能否结构化?能否验证?
需要大量视觉判断的任务就不适合命令行。比如挑选构图好看的图片、精调一份 PPT 排版、在视频里逐帧找某个镜头,这些场景下图形界面的优势太明显,硬用命令行要么做不到,要么做得很别扭。还有一类是纯一次性且交互繁复的操作,比如偶发地搜索某个不常用软件的设置项,打开窗口点两下可能比查命令文档更快。另外,命令行更擅长处理"文本流",如果你面对的是强交互的富文档格式,先把它们转成文本再用 CLI 处理往往更现实。
边界和适用区之间其实没有严格标准,只认一条:命令行帮你节省的重复劳动,应该远大于你学习命令行所花费的时间。这条账算清楚,你就不会走极端。
2. 一把趁手的"武器库":CLI 全能工具箱的选型清单
2.1 文件与文本处理:fd、ripgrep、fzf 三件套
经典的find和grep我当然会用,但日常效率拉满靠的是更现代的三件套。
- fd替代
find做文件检索。它语法直觉,fd pdf直接在当前目录下找所有 PDF 文件,速度和可读性都比find好太多。配合-e按扩展名过滤、-s区分大小写,日常查询基本一行搞定。 - ripgrep(命令名
rg)替代grep做文本搜索。它默认递归搜索、自动跳过.gitignore忽略的文件,而且多线程实现让它在大型代码仓库里的速度碾压传统 grep。我定位日志和源码关键字基本只靠它。 - fzf是模糊查找器,也是我把历史命令变得好用的关键。
Ctrl+R可以像搜索框一样从历史命令里模糊匹配,配合fzf还能做文件预览、进程选择、Git 分支切换。
这三个工具的安装都很简单:macOS 上brew install fd ripgrep fzf,主流 Linux 发行版也有对应软件包;Windows 用户建议直接装一个 Git Bash 或 WSL 再来体验,兼容性会顺畅很多。
2.2 结构化数据:jq 与 yq
现代命令行的重头戏是处理结构化数据,尤其是 JSON 和 YAML。jq是 JSON 的瑞士军刀,curl拉回来的接口数据、日志里的 JSON 行、配置文件里的复杂嵌套,都能靠它筛选、转换、格式化。yq则补上了 YAML/TOML 的处理能力。有个需要注意的细节:yq在社区里有基于 Python 和基于 Go 的两套实现,两者语法略有差异,我建议选中一套长期使用,别混着写,否则很容易踩语法不一致的坑。
我用jq做最多的事情,是从接口响应里抽取我需要的那几个字段,然后直接拼成表格或 CSV。比如:
curl -s https://api.github.com/repos/curl/curl \ | jq -r '"stars: \(.stargazers_count), forks: \(.forks_count)"'这里-r表示输出原始字符串而不带引号,配合模板字符串就能把数据直接变成可读文本。类似的需求非常高频,一旦用熟,你甚至会觉得打开浏览器去查 JSON 响应是一种浪费时间。
2.3 网络请求与开发协同:curl、httpie、git、docker
接口调试最基础的工具是curl,它几乎存在于所有 Unix 环境;如果你追求更友好的输出,httpie的高亮和自动格式化会让人更愿意"看一眼返回结果"。我建议两个都装,curl用在脚本里保证可移植性,httpie用在交互式调试时节省时间。
开发环节里,git自不用说,gh(GitHub 官方命令行工具)能把 issue、PR、release 的操作都变成命令,适合重度使用 GitHub 的人。docker是环境一致性神器,我经常把一组工具链(jq、python、ffmpeg 等)打包成一个镜像,在任何机器上一键跑起来,完美避开"我这机器没装 xxx"的尴尬。
make可能看起来是 C 项目的专属,但我的一个私藏用法是:用它来给反复执行的命令加上"任务名"。比如make deploy、make sync-data,写进文件后团队伙伴不用记一长串命令,直接敲任务名就行。
2.4 系统感知与媒体处理:htop、ncdu、ffmpeg、ImageMagick
系统监控方面,htop是比top友好得多的资源管理器,按键操作、树形展示、F6 排序,刚上手也没压力。磁盘占用分析我常用ncdu,它能在终端里交互式浏览目录占比,很快找出哪个目录把磁盘塞满了。处理网络和端口问题时的ss、lsof也要随叫随到。
媒体处理经常是被低估的命令行场景,实际上ffmpeg加ImageMagick已经覆盖了我工作中 90% 的媒体需求。批量把图片从 PNG 转 JPG、统一缩放尺寸、压缩质量,交给convert一行就能完成;视频转格式、裁剪片段、抽帧,ffmpeg的参数非常稳定。这类工具初看参数复杂,但用熟了之后,你会发现图形界面里的批量处理功能背后其实也是同一套逻辑。
2.5 选型逻辑:怎么决定装哪些、替换哪些
工具选型我坚持三个原则:高频优先、组合性强、跨平台。先把你平时重复最多的动作列出来,比如文件搜索、日志查看、接口调用,按频率排序,优先给高频动作配上最好的工具。其次,挑选那些能放进管道、能被脚本调用的工具,孤立的"全家桶"式命令反而会限制组合。最后,尽量选择在 Linux、macOS、Windows 三端行为一致的实现,否则同一个命令在不同机器上结果不同会非常痛苦。
为了方便对照,我把上面提到的主力工具汇总成一张表:
| 类别 | 工具 | 主要用途 | 上手难度 |
|---|---|---|---|
| 文件检索 | fd | 快速查找文件,替代 find | 低 |
| 文本搜索 | ripgrep | 在大目录/日志中搜索关键字 | 低 |
| 模糊查找 | fzf | 交互式搜索历史命令、文件 | 低 |
| JSON 处理 | jq | 筛选、转换 JSON 数据 | 中 |
| YAML 处理 | yq | 处理 YAML/TOML 配置 | 中 |
| 网络请求 | curl / httpie | 调接口、下载、调试 | 中 |
| 版本控制 | git / gh | 代码管理与 GitHub 运维 | 中 |
| 环境容器 | docker | 一致的运行环境 | 中 |
| 任务编排 | make | 把多步命令变为任务名 | 低 |
| 系统监控 | htop / ncdu | 资源监控与磁盘分析 | 低 |
| 音视频处理 | ffmpeg | 格式转换、剪辑、抽帧 | 中 |
| 图像处理 | ImageMagick | 批量缩放、格式转换 | 中 |
3. 让命令组合起来干活:管道、参数与脚本的三个实操案例
3.1 案例一:用一条命令把杂乱下载目录按类型归档
我电脑的 Downloads 目录是一个典型的重灾区:图片、PDF、安装包、压缩包堆在一起,找东西全靠搜索。写一个基础的归档循环很简单:
cd ~/Downloads for f in *; do [ -f "$f" ] || continue ext="${f##*.}" mkdir -p "archive/${ext}" mv "$f" "archive/${ext}/" done这里有两个细节值得解释。"${f##*.}"是 Shell 参数扩展,表示从变量f的末尾开始,删除最长匹配*.的前缀,剩下就是扩展名。用双引号包住所有变量引用,是因为文件名可能带空格,不加引号会被拆成多个参数,导致mv报错。[ -f "$f" ] || continue则是跳过目录、软链接等非普通文件,避免把子目录也当成文件搬走。
这个循环最粗糙的版本有个缺点:无扩展名的文件会把整个文件名当成ext,因此生产环境我会改成基于case的模式匹配,把已知类型归入固定分类。另外,第一次跑之前一定先备份或者在副本目录测试,批量mv如果判断失误,文件四散到错误目录里,恢复起来很麻烦。
3.2 案例二:批量拉取多页接口数据并汇总成表格
很多接口都有分页机制,一次最多返回一百条数据,但你需要拉五页甚至五十页。手动改 URL 显然是低效的,用循环加jq就能自动化。我用 GitHub API 拉某个仓库最近几页提交记录做演示:
for page in $(seq 1 5); do curl -s "https://api.github.com/repos/git/git/commits?per_page=100&page=${page}" \ | jq -r '.[] | [.sha[0:8], .commit.author.name, (.commit.message | split("\n")[0])] | @tsv' done | sort -u > commits.tsv这条命令的关键点在于jq的字段提取:.[]遍历数组的每个元素,[字段1, 字段2, 字段3] | @tsv把想要的字段拼成一行 Tab 分隔文本。sort -u在最后去重,避免接口数据和上一次执行产生重复。split("\n")[0]是只取提交信息的第一行,因为提交说明经常有换行,不带这个处理的话输出表格会很乱。
实际跑下来五页数据大概两秒内完成,输出是一个干净的commits.tsv。如果你的数据是 CSV 或需要进一步分析,awk、column -t甚至直接导入电子表格都能接着处理。这个模式完全可以推广到任何分页 REST 接口,核心思想就一句话:把"一页一页手动看"变成"一次性拉全量再结构化过滤"。
3.3 案例三:半小时级别的日志快速定位与预警
日志分析是命令行的高频场景。假设你有一个access.log,每一行是 Nginx 或 Apache 的标准访问日志,第一列是客户端 IP。想立刻知道哪些 IP 访问最多,一行命令就够:
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10awk '{print $1}'提取第一列,sort让相同 IP 聚在一起,uniq -c统计每类出现次数,sort -rn按数字倒序排,最后head -10取前十。整条管道就像一条流水线,每一个环节只做一件事。
想统计某一天内 5xx 状态码的数量,可以用更精细的awk:
awk '$9 >= 500 { count++ } END { print "5xx count:", count }' access.log$9对应状态码字段,>= 500把所有 5xx 错误归为一类,END块在全部行处理完后输出累计值。这里的逻辑是"边读边统计",不需要把整个文件加载到内存,几 GB 的日志也能扛。实战中我还会叠加grep按关键词先过滤,再进入统计管道,比如先选出来自某个接口的请求,再做耗时排序,两分钟内就能定位到异常来源。
3.4 从"命令"到"脚本":把成功案例固化为可复用的 .sh
当一条命令反复使用超过三次,就该把它升级成脚本。我以 3.2 的分页拉取为例,写一个带参数的版本:
#!/usr/bin/env bash set -euo pipefail repo="${1:?用法: fetch_commits.sh <owner/repo>}" pages="${2:-5}" for ((p = 1; p <= pages; p++)); do curl -s "https://api.github.com/repos/${repo}/commits?per_page=100&page=${p}" done | jq -r '.[] | [.sha[0:8], .commit.author.name, (.commit.message | split("\n")[0])] | @tsv' \ > commits.tsv wc -l commits.tsv这里最值得学习的是脚本的前三行。#!/usr/bin/env bash让脚本在多种环境中都能找到正确的解释器;set -euo pipefail是 Shell 脚本的安全三件套:-e让任何一条命令出错就立即退出,-u防止引用未定义变量,pipefail让管道中任何一个环节失败都导致整个管道返回失败。${1:?...}是参数校验,缺失参数时直接打印提示并退出,比之后依赖报错要友好得多。
执行时./fetch_commits.sh git/git 10就能拉十页数据。把脚本放进~/bin并加入PATH,它就成了你自己的"私有命令"。
4. 把 CLI 养成"肌肉记忆":环境配置、别名与自定义命令
4.1 Shell 选型与基础配置:为什么我推荐 zsh 加插件
CLI-Anything 的地基是 Shell。我用的是zsh,配合oh-my-zsh或更轻量的插件组合,理由不是花哨的配色,而是它的补全和插件生态能明显减少击键次数。zsh的自动补全比默认bash更强,特别是路径补全、命令行参数补全;历史命令共享和模糊匹配也能靠插件一键启用。当然,如果你不想换环境,bash同样能做所有事情,只是体验上需要自己配一些东西。
我的.zshrc里比较关键的配置是这三项:
HISTSIZE=20000 SAVEHIST=20000 setopt HIST_IGNORE_SPACE # 命令前加空格则不记录,方便临时敏感操作 autoload -Uz compinit && compinit历史记录是最被低估的资产。我从来不背复杂参数,靠的是history和模糊搜索:半年前用过的一条ffmpeg命令,Ctrl+R输几个关键字就能找回来。所以把历史容量调大,比你多记一百条命令语法收益高得多。
4.2 别名设计:高频操作的"短密码"
别名是让长命令变成肌肉记忆的最快方式。我设计的别名原则很简单:只有高频且无歧义的操作才配拥有别名,避免为了省几个字符给不常用命令也起名,结果自己都忘了它代表什么。
下面是一组我实际在用且比较安全的基础配置:
| 别名 | 展开 | 用途 |
|---|---|---|
ll | ls -lh | 人性化文件列表 |
la | ls -lah | 含隐藏文件的完整列表 |
.. | cd .. | 快速返回上级目录 |
now | date +"%Y-%m-%d %H:%M:%S" | 输出当前时间 |
serve | python3 -m http.server 8000 | 当前目录起临时 HTTP 服务 |
qfind | fzf --preview 'bat {}' | 带预览的文件模糊查找 |
这些别名都写在.zshrc里,每次新环境安装时自动生效。serve是我用得很多的一个,临时分享文件、测试前端页面,一条命令就把当前目录变成可访问的站点,比开图形化编辑器或 FTP 省事太多。
4.3 自定义函数:超越别名的能力
别名只能做静态替换,函数则能处理参数、循环、判断。一个最简单的例子:
mkcd() { mkdir -p "$1" && cd "$1" }mkcd docs/archive会先创建目录再切进去,避免mkdir和cd两步操作。类似这种"组合型"函数,能把两三个常用命令封装成一个动词。
再分享一个我用于批量压缩图片的函数:
compress_imgs() { for img in *.png; do [ -e "$img" ] || continue convert "$img" -quality 80 "${img%.png}.jpg" done }注意${img%.png}是去掉后缀,生成的新文件名是 JPG 格式。这函数补上了很多图形软件"批量导出"功能才能做的事情,而且完全本地执行、路径可控。函数和别名的分工很清楚:别名解决"太长"的问题,函数解决"需要参数"的问题。
4.4 从手动敲命令到"半自动工作流":记录、回放与任务化
当你积累了一批顺手命令后,下一步是把它们组织成"任务"。最简单的组织方式是用Makefile,把常用操作写成目标:
sync-data: ./scripts/fetch_data.sh ./scripts/transform_data.py ./scripts/upload_data.sh deploy: ssh deploy@myserver "cd /app && git pull && systemctl restart app"之后你在命令行里只要敲make sync-data,一串命令按顺序执行,日志清晰,失败时还能靠退出码判断环节。比起在终端里重新回忆三个脚本的调用顺序,任务名的记忆成本低得多。
我自己的习惯是:新任务先手动敲一遍确认效果,确认无误后写成脚本,再把脚本挂进Makefile或定时任务。这样既保证每个环节都经过实际验证,又让整个流程逐渐沉淀成可复用的资产。用一年时间,你的~/bin和Makefile会变成最值钱的效率库。
5. 踩坑记录:CLI-Anything 实践中最容易翻车的四个场景
5.1 文件名的空格、通配符与引号:Shell 展开顺序的教训
Shell 处理命令时有一套固定的展开顺序,通配符先展开,然后才轮到变量和命令替换。这意味着如果你写for f in *.txt,文件名里的空格并不会在循环内部被拆开,因为通配符展开的结果是"一个包含空格的完整文件名",而不是多个独立词。
真正的坑在管道和read循环里。我最早写的批量处理脚本长这样:
find . -name "*.txt" | while read -r f; do echo "处理: $f" done单看没毛病,但当文件名包含空格时,read默认按行读取并做分词,"一个 文件.txt"会被拆成一个和文件.txt两部分。解决方法是把读取的分隔符改成空字符:
find . -name "*.txt" -print0 | while IFS= read -r -d '' f; do echo "处理: $f" done-print0让文件名之间用空字符分隔,IFS=取消默认分隔符,-d ''指定按空字符读取。这套组合是所有处理带空格文件名的标准姿势,写脚本时看到文件路径变量,第一反应就该检查有没有加引号、有没有用-print0。
5.2 管道里的变量为什么"丢"了:子 Shell 的作用域陷阱
有一次我想统计当前项目下所有.log文件的数量,写了一段看起来完全正确的代码:
total=0 find . -name "*.log" -print0 | while IFS= read -r -d '' f; do total=$((total + 1)) done echo "total=$total"结果total还是 0。原因在于管道运算符|会创建一个子 Shell,循环体在子 Shell 里执行,循环结束后变量total的修改并不会传回父 Shell。这是 Shell 新手最常撞上的暗坑之一。
三种修法里我最推荐进程替换:
total=0 while IFS= read -r -d '' f; do total=$((total + 1)) done < <(find . -name "*.log" -print0) echo "total=$total"< <(...)把find的输出当作文件输入,循环在当前 Shell 进程中运行,变量修改当然能保留。如果遇到更复杂的状态累计,建议直接改用awk或 Python 处理,避免在 Shell 里绕弯子。
5.3 Windows、Linux、macOS 的命令差异:同一套脚本三处翻车
命令行工具并不天然跨平台。我一次在 macOS 上写好的sed -i 's/foo/bar/g' file.txt放到 Linux 上执行直接报错,原因就是 macOS 自带的 BSDsed要求-i必须带参数,而 GNUsed允许裸用-i。
解决思路有三层。最省事的是统一环境:在 Windows 上装 WSL 或 Git Bash,macOS 上通过brew install coreutils装 GNU 工具链,让所有机器尽量跑同一套命令。其次是规避差异,优先用 Python、Perl 这类跨语言脚本而不是sed -i。比如跨平台替换文件内容,我推荐:
perl -pi -e 's/foo/bar/g' file.txt第三个坑是换行符。Windows 环境下保存的脚本文件常带 CRLF 换行,放到 Linux 上一跑就报bash\r: command not found。解决办法是dos2unix script.sh转换成 LF,或者在编辑器里设置保存为 LF。这些差异你第一次遇到会卡很久,但只要把"先确定运行环境、再选命令"养成习惯,就不会反复栽跟头。
5.4 安全底线:rm -rf、权限与不可逆操作的三条自保铁律
命令行最大的风险不是打错命令,而是批量操作太顺手,造成了不可逆的破坏。我在这上面吃过不小的亏:一次清理临时文件时find . -name "*.tmp" -delete写错了路径,把正在使用的缓存目录删了个干净。
现在我给自己定了三条铁律。第一条,所有批量删除和覆盖操作必须支持 dry-run。先用find ... -print或者rsync --dry-run把将要做的事情完整打印出来,确认无误再去掉干跑参数真正执行。第二条,命令输出先看一眼再进管道。尤其在使用rm、mv、> file覆盖重定向之前,先单独跑一下命令查看结果。第三条,脚本必须可重启、可回滚。添加set -euo pipefail,重要操作前先备份,尽量把文件移动到回收目录而不是直接删除。
另外,不要在脚本里硬编码密码或凭据,不要随手sudo。权限越界会放大错误的影响范围,任何命令在 root 权限下出错,代价都是倍增的。把这些底线刻进习惯里,CLI-Anything 才是真正可持续的高效,而不是一场灾难性的冒险。
6. 把 CLI-Anything 再往前推一步:构建自己的命令行工具
6.1 用 Shell 脚本封装一个"私有工具箱"
当脚本数量超过十个,散落在~/bin里的独立文件会变得难找、难记。我建议把它们聚合到一个子命令工具里,比如建一个mytools脚本,用case实现子命令分发:
#!/usr/bin/env bash set -euo pipefail cmd="${1:-help}" shift || true case "$cmd" in archive) archive_files "$@" ;; fetch) fetch_commits "$@" ;; logtop) show_top_ip "$@" ;; help|*) show_help ;; esac这样我只要记住一个命令名mytools,各种功能都是它的子命令:mytools archive ~/Downloads、mytools fetch git/git 5、mytools logtop access.log。相比一堆零散脚本,这种方式在--help提示和心智负担上都友好得多。放在~/bin/mytools并把这个目录加入PATH,任何目录下都能直接调用。
6.2 子命令的健壮性:帮助文档、错误处理与退出码
一个合格的子命令工具箱不能只有功能实现,还要有边界处理。我的每个函数都会做三件事:参数缺失时给出明确用法、错误信息输出到标准错误、返回非零退出码让上层脚本能感知失败。
下面是一个帮助函数的示例:
show_help() { cat <<EOF 用法: mytools <command> [options] 命令: archive <dir> 按扩展名归档指定目录文件 fetch <repo> <n> 拉取 GitHub 提交记录,默认前 5 页 logtop <file> 统计访问日志中 IP 出现次数前十 选项: help、-h、--help 显示帮助 EOF }实际叠加set -euo pipefail之后,任何一个函数内部出错,整个mytools都会带着错误码退出,不会出现"命令失败但看起来像成功"的状态。这个设计对后续自动化非常关键,因为它让脚本行为可预测、可被外部系统感知。
6.3 版本管理与跨机器同步:用 Git 维护 dotfiles 与工具脚本
CLI-Anything 的资产不只是几个脚本,还有.zshrc、.bashrc、Makefile、工具函数。我强烈建议把这些 dotfiles 和脚本用 Git 管理起来,存进私有仓库。新机器上只需要:
git clone git@yourhost:you/dotfiles.git ~/.dotfiles cd ~/.dotfiles && ./install.shinstall.sh负责创建软链接,把仓库里的.zshrc、mytools链接到正确位置。这套机制让我能在换了电脑之后两小时内恢复全部命令行环境,而且每次配置改动都有历史记录,改坏了可以随时回退。不要觉得这是过度工程,当你第三次在另一台机器上重新敲一遍alias配置时,就会明白版本管理的价值。
6.4 给刚接触命令行的人:一个最小启动路径
如果你看完这篇文章觉得很有道理,但不知道从哪开始,我建议按这条路径推进:先装好fd、ripgrep、fzf和jq这四个工具,花一个下午把它们的常用参数过一遍。然后挑一件你每周都会做的重复任务,比如整理下载目录、批量压缩图片、统计日志,用文中的案例模式写出第一个脚本。最后给你的核心操作加上别名,把脚本放进~/bin。
我个人的切身体会是:命令行效率不是靠记住几百条命令堆出来的,而是靠不断把重复动作顺手固化成脚本、别名和工具堆出来的。刚开始你会觉得慢,每写一个脚本都要查半天语法,但积累两三个月后,你的工具箱会像滚雪球一样越来越顺手。到那时候,CLI-Anything 就不再是一个抽象概念,而是你工作方式的自然延伸。最后再分享一个小技巧:每完成一个新脚本,花一分钟写一段注释记录它的用法和适用场景,三个月后回头看,你会感谢当时那个"多写一句话"的自己。