ARTICLE DETAIL

资讯详情

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

CLI Anything:用命令行打造全能终端工作流

CLI Anything:用命令行打造全能终端工作流 “CLI-Anything”这个词我盯了很久才回过味来——它其实不是某个具体软件的名字而是一种思路把你能想到的几乎所有高频操作都收敛到一个终端里完成。搜索文件用命令行筛选历史命令用命令行看 Git 提交记录用命令行连改配置文件、查数据库、问 AI 问题也全都在命令行里做。这篇文章我想系统梳理一下我这些年搭起来的“CLI 万能工具箱”选型思路、配置方案、真实工作流以及哪里该停下来换回 GUI。内容偏实战已经用过终端但想更进一步的朋友应该能直接“抄作业”。1. 为什么我坚持把一切操作搬回命令行先说动机。很多人的终端使用停留在“偶尔执行一条命令”的状态装个包、拉个代码、跑个脚本其余时间都泡在 IDE 和文件管理器里。我原本也是这样直到有一天我需要从一个几十 GB 的工程里找一段老代码。打开 IDE 的全局搜索转圈等了快半分钟它给我返回了 300 个结果但没法按相关性快速过滤我抽出终端用rg加几个条件一筛两秒就锁定了文件。从那一刻我开始意识到命令行的价值不是让你摆脱鼠标而是让你拥有一个“可脚本化、可组合、可自动补全”的统一操作层。GUI 应用各做各的快捷键不互通自动化能力也五花八门终端里的工具却有一个共同的约定文本进、文本出一个程序的输出可以直接送给另一个程序当输入。这个约定带来的组合能力才是 CLI Anything 最大的资产。当然我并不是“命令行原教旨主义者”。如果有人叫我用vi看图片、用终端剪视频我会直接拒绝。CLI 适合处理的是搜索、筛选、变换、执行、编排这一类结构化操作。视觉审美类、复杂排版类工作GUI 永远更高效。就像你可以在终端里“看”一张图片的元信息和文件尺寸但不该硬着头皮用字符画去欣赏照片。所以 CLI-Anything 的真实含义是在一个你不需要离开的地方做完所有能高效完成的事并且让这些事互相能“接得上”。比如文件搜索结果可以直接变成 git 操作的输入git 的改动列表又可以通过管道变成批量重命名的依据。这种衔接没有任何 GUI 能给你。1.1 为什么说“让命令互相接得上”最关键很多教程只教单个命令但真正拉高工作效率的是命令与命令之间的管道。举个例子rg -l TODO src/ | xargs wc -l这条命令的意思先搜索所有包含TODO的文件然后把文件名传给wc -l统计行数。一步之间你从“代码搜索”跳到了“工作量评估”。如果是在 GUI 里你需要先复制搜索结果再去另一个工具里处理中间还可能丢失上下文。终端的世界里没有“粘贴”这一步。另一个打动我的点是命令行工具的迭代速度奇快。近几年取代ls的eza、取代grep的ripgrep、取代cat的bat这些工具几乎是一年一个台阶。GUI 应用很难像这样快速更新并保持向后兼容因为它们背负着菜单、按钮、配置界面这些“体积包袱”。1.2 这套思路适合谁我见过三批人后端和运维开发天天跟服务器打交道终端摸得最多把这套流程搭起来收益最直接数据方向的人处理日志、分析 JSON、批量重命名CLI 的效率碾压鼠标点选普通办公用户其实只需要学会rg fzf vim三件套就能告别在文件夹里来回翻找的日子。如果你是彻底的编程新手连终端是什么都没概念我不建议一上来就搭整套工具链。先学会基本命令再逐步叠加。下面每一章我都会标注用途和难度方便你自己判断。2. 起始装备高频操作的最优解选型“CLI-Anything”不是某一个工具而是一组工具的组合。我目前的配置里最核心的四件套是eza列目录、ripgrep搜内容、bat看文件、tmux管会话。先来说说为什么是它们以及我踩过的坑。2.1 用 eza 替代 ls目录列表能多给你多少信息传统ls的问题不是不能看而是“看了也白看”——文件类型不直观权限和大小挤在一坨目录树更是难搞。eza的出现解决了这些痛点它比ls更友好的地方我用一个例子就能说明eza -lh --git --group-directories-first这条命令会展示目录内所有文件显示图标分组、Git 状态、可读文件大小并且文件夹排在前面。执行完你能一眼看出哪些文件被修改过Git 状态列有标记、谁是今天的产物、谁是老古董。如果你经常在项目里改文件却忘了改了什么这个命令能让你不用打开 IDE 就有概念。我在.zshrc里放了几个 aliasalias lseza --group-directories-first alias lleza -lh --git --group-directories-first alias treeeza --tree --level3 --group-directories-first注意ls的--group-directories-first很重要它会改变你对一个目录的“第一印象”。没有它巨量的文件会淹没文件夹你一屏扫下来全是碎片信息。2.2 用 ripgrep 替代 grep速度带来的体验升级grep慢和难用的根本原因是它遵守教科书式的正则写法而且默认不跳过.gitignore里的文件。真实项目的目录动辄几万个文件用grep -r搜一次小半分钟很正常。ripgrep命令名rg相比之下有三点碾压级优势默认智能跳过.gitignore、二进制文件、隐藏目录不用加一堆参数用 Rust 实现多线程 内存映射速度上比grep -r快一个数量级输出格式友好带颜色、带行号、带文件名而且格式是通用约定方便后续管道处理。日常我常用的姿势rg -l ERROR logs/ # 只输出文件名 rg -n class Foo src/ | head -50 # 带行号输出 rg -i todo|fixme --glob !vendor/** . # 忽略指定目录最爽的是它和 fzf 配合时的体验。你输入rg -l 关键词 .得到一串文件列表然后直接接| fzf用模糊搜索进一步过滤。我后面会专门讲 fzf但它的前提是一个足够快的搜索器——rg就是这个“引擎”。2.3 用 bat 替代 cat阅读源码和配置文件的正确姿势很多人写文章推荐bat时会说“让cat变好看”这其实低估了它。bat最大的价值不只是配色而是默认带行号、语法高亮、Git 变更标记和分页。看一个配置文件时行号能让你直接定位要修改的位置和rg搜索的行号对应上整个工作流都顺畅起来。举一个真实场景我发现nginx.conf里某个 location 块有语法问题。rg -n location /etc/nginx/nginx.conf输出可能是一串行号。然后我直接bat --line-range 40:80 /etc/nginx/nginx.conf只显示 40 到 80 行带着语法高亮看哪儿有问题一目了然。这比cat 编辑器反复切换高到不知哪里去了。另外一个小技巧给bat设置一个--theme我用的是ansi颜色方案因为它在真终端里效果最稳定不会因为某个终端配色没调好变成一团荧光绿。2.4 tmux让“上下文”不因为关闭窗口而丢失我觉得很多新手对终端最大的抱怨是“一关就没有了”。你在一个窗口里跑着日志跟踪、在另一个窗口写代码结果一不小心把所有终端关掉所有工作上下文全丢。tmux要解决的就是这个问题它在终端里维护持久会话你可以随时分离detach再重新接回来就像把工作台冻结了。我的基本使用习惯tmux new -s work # 新建会话 tmux ls # 查看会话列表 tmux attach -t work # 重新接回会话进入会话后用前缀键Ctrlb切分窗格。Ctrlb c建新窗口Ctrlb %左右切分Ctrlb 上下切分。这套东西初学有一点点记忆成本但一旦形成肌肉记忆就再也回不去那个“开十几个终端窗口”的状态了。2.5 选型时我的原则优先选 Rust 工具链我强烈建议新人不只盯着具体命令而是留意一个趋势新一代 CLI 工具很多是 Rust 写的。为什么因为 Rust 编译出的二进制是单文件、无运行时依赖、天生并发安全更重要的是性能真的能感觉到。eza、rg、fd、bat、zoxide、yazi这些工具都是 Rust 家族。当你部署到一个新服务器时扔一个二进制进去就能跑不用装 Node、Python 环境幸福感极高。选型时可以按照这个优先级功能满足度高不高能不能解决我的直接问题交互延展性强不强输出能不能被管道接走跨端移植成本低不低换机器、换系统能否轻松迁移配置。3. 文件操作增强精确搜索与快速跳转文件操作是终端使用频率最高的一类场景但很多人只会cd、ls、cp老三样。这一章我详细讲我实际配置的搜索、跳转、文件管理和批量处理方案。3.1 fzf把模糊搜索变成所有 CLI 工具的“连接器”fzf是一个模糊查找器但它真正的身份是“终端交互的万能胶水”。你给它任何候选列表它会打开一个交互式搜索框你敲几个字就能过滤回车则把选中的结果输出到标准输出于是结果可以被任何其他命令接到后面用。基本用法find . -type f | fzf执行后你会看到一个全屏的模糊搜索界面敲 “appa” 就能匹配到AppConfigAdapter这类文件名。选中的结果会打印到终端你可以把它赋给变量继续操作。更强大的用法是和历史命令配合。我在~/.bashrc/~/.zshrc里设置# 用 CtrlR 实现“模糊搜索历史命令” export FZF_CTRL_R_OPTS--preview echo {} --preview-window down:3:wrap任何时候按下CtrlR直接输入关键词就能从历史中定位命令支持模糊匹配再也不用反复按方向键翻了。3.2 zoxide智能记住你常用目录替代一半的 cd你有没有这样的经历项目目录深达七八层每次进都要cd /home/user/work/project/backend/service/core敲得手疼。zoxide做的事是“根据访问频率和最近访问记录把目录排序”然后你只需要z core它就能跳到最匹配的目录。它是学习型的越常用越准。比如我既访问过project/backend/core也访问过notes/linux/core那我输入z core它会优先去最近访问的那一个。安装方式# 安装本体然后用环境变量启用 curl -sSfL https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | sh # 在 shell 配置里加 eval $(zoxide init bash) # zsh 则换成 zoxide init zsh为了让z的体验更完整我定义了zi让它也接入 fzfalias zizoxide query --interactive当你目录太多记不住名字时zi会弹出一个模糊搜索列表选中即跳转。3.3 yazi在终端里操作文件像 IDE 一样顺手有人可能会说“文件管理我还是喜欢用鼠标拖拽”。我理解但在终端里有一个工具做得很接近文件管理器的体验甚至更好那就是yazi。它是 TUI终端界面文件管理器支持分栏预览、复制粘贴、重命名、批量选择、内置终端命令执行以及异步加载图片预览。第一次打开yazi你会以为是编辑器但它其实是个文件管理器。按方向键移动空格选中文件V选择所有y复制x剪切p粘贴。按Enter进入目录按--返回上级。最重要的是它支持挂钩 shell 命令在yazi里按;可以直接执行命令比如rg搜索当前目录。你选中的文件还能作为结果传给外部命令。我的常用操作流打开yazi按/输入文件名过滤选中一批文件按;执行zip -r backup.zip直接打包按q退出回到 shell你还可以对刚才选中的文件继续操作。有人问“这不是多此一举吗”关键在于yazi把“浏览、选择、执行”放在同一个界面里不用来回跳转减少了认知损耗。3.4 批量重命名和批量内容替换的“零失误”姿势批量重命名是我见过大多数人“手动操作半小时”的重灾区。实际上用rename命令可以秒杀rename s/\.js$/.ts/ *.js这就是把当前目录所有.js后缀改成.ts。注意它是 Perl 正则语法可以写复杂规则比如rename s/(.*)\.([a-z])$/report_$1.$2/ *.pdf批量替换文件内容我用手感最稳的组合是rg perl -pirg -l old_text . | xargs perl -pi -e s/old_text/new_text/g这一步先确认搜索范围再在指定文件里替换。如果你加了--dry-runperl没有自带 dry-run但你可以先用rg看清楚就不会出现“全局替换但改了不该改的文件”这种事故。3.5 fd一个比 find 更“现代”的查找命令尽管find的威力很大但它的参数写成-name、-type f这类形式容易记混而且输出默认不含排序。fd是个更好的替代品fd -e md docs # 在 docs 里找所有 markdown 文件 fd -H -x wc -l # 在隐藏文件列表里执行 wc -l和fzf配合可以实现极速文件搜索fd -t f | fzf我在很多配置里直接用fd替代find只有涉及非常复杂的逻辑表达式时才回头找find搏杀。4. 让终端真正接管 Git 与编码工作流编码过程中最打断思路的事情是什么是切换。你在写代码想看一眼 Git 状态切到 GUI Git 客户端点两下再切回来上下文已经碎掉了。CLI-Anything 要做的就是把 Git 也收进终端。4.1 lazygit终端里的可视化 Git 管家lazygit的界面看起来像 GUI但运行在终端里而且完全可以用键盘操作。它把仓库的分支、提交、工作区、暂存区、拉取推送等操作都集中在一屏上下文中1查看状态2查看日志3查看分支空格键把文件加入暂存区c提交怎么写 message 都会弹出编辑器p推送f拉取。对我而言它最大的价值是解决“交互式 rebase 恐惧症”。用lazygit进入日志视图选中某条提交按r就能用上下方向键调整提交顺序或标记为 fixup、squash。这比命令行输入git rebase -i HEAD~3然后还要对着 vi 编辑pick和squash要直观很多对中级用户尤其友好。4.2 delta给 git diff 加上语法高亮和逐行标注git diff默认的输出信息足够但视觉上不够清爽。delta是一个 diff 高亮分页器它最大的贡献是让改动块边界清晰逐行变化一眼可见甚至你还能看到被删除的行和被新增的行之间“错位”对应得怎么样。配置在~/.gitconfig[core] pager delta [delta] line-numbers true side-by-side true加上side-by-side后左右分栏对比。注意终端宽度太小时这个模式会换行看起来不舒服所以我会在delta配置里加一行[delta] side-by-side false line-numbers true多数时候逐行显示已足够只有在非常复杂的冲突场景我才会手动开左右对比。4.3 用 rg sd 完成跨文件“安全重构”IDE 的重构功能很强但你有没有遇到过这种场景只想改一个目录下的文件不碰其他目录IDE 的全局重构又太重。这时候用rgsd一个类 sed 的现代化替换工具反而更敏捷。sd的优势是字符串替换默认按字面量不容易踩正则转义的坑而且支持简单的正则模式rg -l from_module src/ | xargs sd from_module new_module如果我想让所有匹配的文件在替换前都先看一遍可以在xargs之前加-p参数实现交互式确认。这种粒度控制是 GUI 重构很难给你的。4.4 快速打开项目和文件的“发射台”配置当项目多起来之后记忆路径本身就是成本。我用的是一个简单脚本思路用一个目录维护项目清单比如~/projects/*写一个函数p用于列出所有项目名交给 fzf 选择选中之后用cd进入。function p() { local dir dir$(find ~/projects -maxdepth 2 -type d -name .git 2/dev/null | sed s|/\.git|| | fzf) [ -n $dir ] cd $dir }这样我敲p回车一个模糊搜索列表弹出来选中的项目直接进入。配合 zoxide 的z基本就告别“手打完整路径”了。5. 文本与结构化数据操作从 jq 到 fzf 的进阶玩法命令行的强项是处理文本但现在的数据更多是 JSON、YAML 等结构化格式。这一章讲讲怎么把这些数据“玩转”。5.1 jq让你在终端里像操作对象一样操作 JSON很多时候我们需要从接口返回的 JSON 里提取字段。比如curl -s https://api.example.com/users | jq .[] | {id, name, email}这会把用户数组拆开只保留三个字段格式清晰再加上筛选jq .[] | select(.age 18 and .active true) | .name我第一次用jq时的感受是“终于不用为了看一眼数据专门写个 Python 脚本了”。建议新手至少掌握四类过滤器.key、.[]、select()、|管道。5.2 yqYAML 的等价方案YAML 在配置文件中非常常见但处理它比 JSON 更隐晦因为缩进和多行字符串很容易出错。yq的语法吸收了大量jq的写法比如yq .services.web.image docker-compose.yml用它可以快速读取和修改 YAML 配置无需打开编辑器手动数空格。我在改 GitHub Actions 工作流、Kubernetes YAML 文件时都会先用yq把结构梳理出来。5.3 把任何命令输出接入 fzf真正的万能交互筛选这一小节的标题几乎就是“CLI-Anything”的缩影。学会 fzf 以后你会发现所有命令的输出都可以变成筛选列表。三个我在日常中高频使用的场景场景一交互式杀进程ps aux | fzf | awk {print $2} | xargs -r kill这里ps aux列出全部进程fzf 让你模糊搜索选中后提取 PID然后杀进程。比起kill手输 PID这个流程危险性可控且直观。场景二交互式切换 Git 分支git branch -a | fzf5.4 历史命令的模糊搜索很多人把 shell 历史只当成一个“有但没有用”的东西因为你老是找不到。我用了两种方式改造它。第一种设置HISTFILE为独立文件然后绑定 fzf。在 Bash 中bind \C-r: \C-u\C-e\C-hfzf-history-widget第二种如果你跟我一样用 zsh直接配置fzf的CtrlR插件它会用模糊匹配而不是前缀匹配。这意味着你记不清完整命令也能搜到而且选中的命令直接编辑而不直接执行可以改。5.5 一行 Python/Perl 命令做复杂文本变换有些文本变换用 sed 写正则反而复杂这时我更喜欢一行 Pythonpython3 -c import sys,json for line in sys.stdin: datajson.loads(line) print(data[user][name]) 虽然这已经不算“一行”但它让 JSON 的处理不再受jq语法限制适合需要跑复杂逻辑的场景。6. 把 CLI 扩展成个人工具中枢数据库、文档与 AICLI-Anything 的最后一块拼图是让它成为你日常的数据、文档和 AI 操作中枢。6.1 数据库操作sqlite3、psql 和 mycli我在本地做数据探索时最常用sqlite3因为它零配置、单文件。如果项目用 PostgreSQL 或 MySQL命令行客户端也很关键psql postgresql://localhost/mydb -c select count(*) from users; mysql -u root -p -e show databases;pgcli和mycli是更友好的替代版支持自动补全和语法高亮。安装后基本无缝替换pgcli postgresql://localhost/mydb工作流中的衔接点在于你可以把查询结果通过管道输送给其他命令比如psql -t -A -c select id from users where statusactive limit 100 | xargs...6.2 API 调试与文档curl jq 的组合拳完整的 API 调试确实有 Postman 这样的 GUI 肥工具但如果你只是想快速验证一个接口、看返回结构curljq是最快的路径curl -s -X POST https://api.example.com/v1/check \ -H Content-Type: application/json \ -d {keyword:CLI} | jq .result不需要单独打开客户端软件不需要保存 collection一行命令拿走。接口测完命令留在历史里下次换参数直接上下箭头即可。这种“一次性的、随手可改”的调试方式是 CLI 独有的优势。6.3 在终端里和 AI 对话把 AI 算力变成管道的一环AI 时代的 CLI-Anything 自然要有 AI 的位置。现在的做法是直接把 AI 能力封装成命令行工具比如llm或自己写一个脚本让它接受标准输入然后返回生成结果再接到其他工具里。我的用法是把 AI 当作“文本处理器”而不是聊天窗口cat requirements.txt | llm 用三句话描述这个项目的依赖风险还可以让它当翻译器rg -l README docs/ | xargs -I {} sh -c cat {} | llm translate to Chinese {}.zh.md实现上你只需要把llm脚本配置为调用某个 OpenAI 兼容接口并将系统提示词设为合理要求。如果你在私有网络环境运行也可以配置本地模型接口数据不出内网。重点在于“接入标准输入输出流”这让 AI 能跟文件、搜索、管道无缝协作成为终端生态的一个原生部分。6.4 用 tmux 和脚本把例行任务自动化日常很多工作其实是重复模式我套路化地写成脚本。比如每日早晨的“巡检”#!/bin/bash # morning_check.sh echo 服务状态 systemctl --failed --no-pager echo 磁盘占用 df -h / | tail -1 echo 内存 free -h | sed -n 2p echo 项目变更 cd ~/work/myapp git status -s然后我把这个脚本放在tmux的一个窗口里每天启动工作区时执行几秒扫描完所有关键指标。有些人觉得这很低级但它比“眼观四处看监控面板”省心得多而且完全受自己掌控。7. 整合成一套 Shell 配置后我的真实使用习惯工具攒了一堆如果不整合它们只是孤岛。最后一步是把它们通过 alias 和快捷键组织成“一套系统”。7.1 我的 Bash/zsh 配置结构我维护了一个~/.dotfiles仓库核心配置分成几个文件~/.dotfiles/ ├── install.sh # 一键安装所有工具 ├── aliases.sh # 常用命令缩写 ├── functions.sh # 自写函数如 p、背影切换 └── env.sh # 环境变量和默认参数aliases.sh片段alias lseza --group-directories-first alias lleza -lh --git --group-directories-first alias treeeza --tree --level3 --group-directories-first alias catbat alias greprg alias findfd注意我并没有把所有基础命令强制覆盖。比如我把grep直接覆盖成rg后有些脚本仍然调用原版因为它们在#!/bin/sh或#!/usr/bin/env bash下有自己的环境变量。所以建议只在交互式 shell 里覆盖而不要写在全局PATH里排最前面。7.2 一段真实的日常流从接到任务到交付以我维护一个内部日志工具为例完整流程在终端里是这样的tmux attach -t work || tmux new -s work # 打开 project p # 查看当前分支状态 lazygit在lazygit里看到两个文件改动退出进入文件快速查看bat -l go src/service/worker.go发现worker.go里有个接口参数名写错了直接vim src/service/worker.go改掉。改完想再编译测试go test ./service/... | tee /tmp/test.log rg -n FAIL /tmp/test.log全部搞定提交lazygit整个过程中p项目跳转、lazygit状态查看、bat文件内容阅读、vim编辑、go test编译验证都在同一个终端里没有一次焦点离开。这就是 CLI-Anything 的“心流感”。7.3 学习优先级先学什么不用学什么新手面对这么多工具容易花眼。我的建议是按阶梯来第一梯队绝对必须学cd、ls、rg、fzf、vim或任何一个能改文件的编辑器。这些构成了“找-看-改”闭环。第二梯队大幅提升效率tmux、lazygit、jq、zoxide。这些解决的是“多会话管理、提交管理、数据提取、快速导航”。第三梯队锦上添花eza、bat、delta、yazi、sd、yq、AI 工具。这些优化体验但不是生存必需品。不用强行学的东西复杂的sed高级正则除非你天天处理日志、Vim 全套自定义能改文件就够、Perl 一行流有 Python 顶着。7.4 我踩过的一些坑和避坑建议坑一alias 覆盖系统工具的副作用。我有一阵把cat覆盖成bat结果在写管道脚本时碰到bat检测到非 TTY自动关掉分页行为不一致导致调试半天。解决方法是只在交互式配置里设置脚本路径里的/usr/bin/cat不受影响。坑二fzf 的边界情况。fzf默认按字符串匹配但对大目录比如 10 万个文件第一次加载还是会卡一下。解决办法是用fd给它预先过滤而不是让 fzf 直接面对全量文件。坑三zoxide 的目录记录混乱。如果你经常在临时目录、build 目录里逛zoxide会把它们记成常用目录导致z跳错地方。每隔一段时间我会用zoxide clean --dry-run查看清理候选再手动清理。8. 从这个体系里收获的几点最终心得写了这么多最后说点感性的东西。CLI-Anything 对我的改变不是“快了多少倍”而是“不再打断思路”。在 GUI 世界里每完成一次任务你的目光要在编辑器、浏览器、文件管理器、Git 客户端之间游移每一次游移都会偷走一点注意力而在终端世界里焦点只有一个那一行命令行。你输入什么它就会按你的逻辑去执行。这套体系不是一次性搭完就结束的。它更像一趟持续的整理今天发现eza有更新版本明天写了一个新函数优化流程后天为某个繁琐步骤写了个小脚本。每一样都在原有基础上继续生长就像你的个人工作台越来越合手。如果你决定开始我建议不要照搬我的全部配置刚开始只引入fzf和rg两个工具等你自己体会到“组合威力”之后再去逐步引入其他组件。配置的过程本身就是对你工作方式的一次重新审视哪些事情是重复的哪些信息的获取成本太高哪些操作经常被“切换”打断想清楚这些比记住任何一个快捷键都重要。最后给一条最实际的建议每周花十分钟审视一遍自己敲得最频繁的五条命令想想能不能加个 alias、加个参数、接个管道让它们更顺手。CLI-Anything 不是一个终点而是一种持续打磨的态度。你的终端会慢慢变成你最顺手的工作台。
返回列表