来源:转自抖音的笙囧同学《为什么总有人极力推荐使用命令行操作而非图形界面》。本文仅作转载与 Markdown 排版,版权归原作者所有。
大多数劝你用命令行的人,给的理由都不太对。
我从本科开始就被劝过好几轮。说法无非那几种:效率高、程序员标配、看起来专业。这些话不算错,但都是表面。真按这些理由去学,你大概会在背了三十个命令之后放弃,然后觉得那帮人是在装。
我自己也是绕了一年多才明白那个真正的理由。它跟“快”没多大关系。
这篇我把它讲清楚。会有不少具体的命令,我一句句翻译成人话,完全没接触过终端的人也能跟着看。另外也会替图形界面说几句公道话,我很反感那种“你还在用鼠标点点点”的鄙视链,那种腔调本身就挺没劲的。
先看一件我上个月真干过的活
那天我要从二十个实验目录里,把每个实验最后一轮的 loss 找出来,排个序,挑出最好的三个继续跑。做过实验的人都知道,这是再普通不过的一件小事。
如果全靠鼠标,流程是这样的:打开第一个文件夹,找到日志文件,双击打开,滑到最底下,肉眼找那个数字,记下来或者抄到表格里。关掉,打开第二个文件夹,重复。二十遍。
我干过这个,大概二十五分钟,中间还抄错了一个数,后来才发现。
用终端的话,是这么一行:
grep -H "final_loss" exp_*/log.txt | awk '{print $1, $NF}' | sort -k2 -n | head -3
我把它拆开翻译一下:
grep -H "final_loss" exp_*/log.txt 的意思是,把所有以 exp_ 开头的目录里的 log.txt 都翻一遍,凡是含有 final_loss 这个词的行都挑出来,并且带上是哪个文件(那个 -H 就是“带上文件名”)。
awk '{print $1, $NF}' 的意思是,每一行我只要两样东西:第一列(文件名)和最后一列(那个数字),中间的废话都不要。
sort -k2 -n 的意思是,按第二列的数值大小排个序。
head -3 的意思是,只给我看前三行。
中间那几个竖线 |,是这一行里最要紧的东西,回头细说。
跑完,不到一秒。
到这儿你可能觉得,哦,所以就是快嘛,二十五分钟对一秒。
不是。这一行真正值钱的地方,是我可以把它存下来。
下周我又跑了一批实验,同样的需求,我不需要再想一遍,直接把这一行调出来回车。我可以把它写进一个脚本,以后每次训练结束自动执行。我可以直接把这一行发到群里给师弟,他复制粘贴就能用在自己的实验上。我甚至可以把它塞进定时任务里,让它每天早上八点自己跑一遍,把结果发我。
而我那二十五分钟的鼠标点击,做完就没了。它没有留下任何东西。下周同样的活儿,我得再点二十五分钟。我没法把“我刚才怎么点的”这件事,传给任何人,也没法交给机器去重复。
这就是那个真正的理由。
手势和语言的区别
我想给你一个类比,是我某次给文科朋友解释这事儿的时候顺口想出来的,后来觉得挺准。
图形界面的操作,像手势。命令行的操作,像语言。
你比划一个手势,对面能看懂,交流没问题,某些场合甚至比说话更直接。但手势有个致命的局限:它没法被精确地写下来。你今天做的一串动作,明天就消失了,你也没法把它寄给一个远方的人,让他做出完全一样的动作。
语言不一样。语言可以被写成文字。写下来之后,它就能被保存、被复制、被传给一万个人、被组合成更长的句子、被后人拿去接着用。人类有了文字之后才开始有历史,原因就在这儿:不是文字比手势聪明,是文字能留下来。
鼠标点击是手势。你在界面上那一连串精妙的操作,是一段无法书写的表演,谢幕即消失。
命令是句子。它天生就是文字,所以它天生可以被记录、被重复、被组合、被传递、被交给别人和机器。
一句话讲完:图形界面的操作是一次性的,命令行的操作是可以被写下来的。效率只是这件事的副产品,不是本质。
想明白这一层之后,后面所有的好处都是顺理成章的,我一个一个说。
那几根竖线:为什么小工具能拼成大工具
回到刚才那一行里的 |,这东西叫管道。它是命令行里最漂亮的一个设计,我第一次真的懂它的时候,有一种小小的惊艳。
它干的事特别简单:把前一个命令吐出来的东西,直接倒进后一个命令的嘴里。
就像工厂流水线。第一个工人只负责筛选,筛完往下传;第二个只负责裁剪,裁完往下传;第三个只负责排序。每个工人都只会一件很小的事,但把他们串起来,就能干成一件很复杂的事。
命令行世界里那些工具,基本都是这个哲学下长出来的:一个工具只做一件事,并且把这一件事做到极好,然后它相信自己会被别人接上去用。
我再给你几个真实的例子感受一下这种拼装的爽感。
想知道二十个实验里,有几个是因为显存不够炸掉的:
grep -l "CUDA out of memory" exp_*/log.txt | wc -l
前半句是“把出现过这句报错的文件名列出来”,后半句 wc -l 是“数一下有几行”。合起来就是“有几个实验炸了显存”。我跑多模态,这条命令用得比我想承认的次数要多。
想看看某个日志里出现最多的报错是哪几种:
grep "Error" log.txt | sort | uniq -c | sort -rn | head
先把所有含 Error 的行抓出来,排序(为了让相同的挨在一起),uniq -c 是“把重复的合并,并数出每种出现了几次”,再按次数从多到少排,取前几名。一行,你就有了一张报错排行榜。
这两条命令我都不是背下来的。我是先有了需求,然后一点点凑出来的,凑过两三次就记住了。
现在你换个角度想想图形界面。
每一个软件都是一座孤岛。看图的软件只会看图,表格软件只会做表,它们之间唯一的通道是复制粘贴这条羊肠小道。你没法把“这个软件的输出”直接接到“那个软件的输入”上,除非开发者专门给你做了这个功能。你能干什么,完全取决于开发者想到了什么。
命令行里,所有工具讲的是同一种语言:纯文本。因为大家都吐文本、都吃文本,所以任何两个工具都能拼在一起,包括作者之间根本互不知道的两个工具。
这就是为什么会有那种感觉:图形界面里你是个用户,你只能用别人给你的功能;命令行里你有点像个组装工,你可以造出开发者压根没设想过的东西。
自由度的差别,来自“大家说同一种语言”。
可复现:这一条对我来说最重要
如果只让我留一个理由,我留这个。
科研这行,有个说出来朴素但做起来极难的要求:你做过的实验,别人(以及三个月后的你自己)得能一模一样地再做一遍。做不到,你那个结果的可信度就是零。
那你想想,一套流程如果是靠鼠标点出来的,你怎么把它交给别人?
录屏?写一份带二十张截图的文档?“先点左上角那个按钮,在弹出的窗口里选第三项,注意不要勾那个复选框”?我写过这种文档,也读过别人写的。软件一升级,按钮换了位置,整份文档就废了。而且截图里永远有你没注意到的细节,别人照着做,结果就是不一样,你俩谁也说不清差在哪。
如果是命令行,交接就是一个文件。
我上个学期把一套数据预处理的流程交给师弟,我给他的不是文档,是一个二十几行的脚本,加几行注释。他跑一遍,得到的东西和我的完全一致,一个字节都不差。有问题,他把命令和报错原文贴给我,我一眼就知道哪儿错了。
这中间的差别不是省事,是确定性。文字是精确的,截图是含混的。
顺着这条往下,你就会理解一大堆现象:为什么开源项目的说明文档里全是命令而不是操作步骤;为什么你去问技术问题,人家让你把命令和完整报错贴出来而不是发截图;为什么论文的复现代码总是一堆脚本。
不是那些人懒得做界面。是文字是唯一能被精确复述的东西。
隔壁组有个师兄,终端里全是自己攒的小脚本。我问他怎么判断一件事该不该写成脚本,他说了句话我一直记着:
同一件事,手动做第三遍还在手动,那就是你的问题了。
这条我后来当成了自己的规矩。第一遍手动,正常;第二遍手动,忍了;第三遍,停下来,把它写成一行或者一个脚本。前期花的那五分钟,后面能省掉几十次。
有些地方你压根没有鼠标可点
前面讲的都是“命令行更好”,这一节讲的是“你没得选”。
我的实验不在自己的笔记本上跑,在实验室的服务器上。那台机器插着几张显卡,放在机房里,没有显示器,没有桌面,没有图标,你想点也没东西可点。你连上去看到的就是一个光秃秃的黑框,一行提示符在那儿闪。
不只是我的实验室这样。绝大多数真正干活的机器,云上的服务器、集群、各种设备,都是这个样子。原因很实在:图形界面很吃资源,而那些机器的每一点资源都想留给计算。
所以只要你的工作需要碰到远程机器,命令行就不是一个偏好问题,是一张门票。
这块顺手给几个我天天用、也建议你早点知道的:
连上远程机器:
ssh 用户名@服务器地址
把本地一个数据文件夹传上去(-avP 里的 P 会显示进度,而且中断了还能接着传,这一点在传几十个 G 的数据集时能救命):
rsync -avP data/ 用户名@服务器地址:/home/xxx/data/
让训练在后台跑,同时把输出和报错都写进日志文件:
nohup python train.py > log.txt 2>&1 &
这条稍微解释一下,因为里头有个新手最容易漏的东西。> log.txt 是把正常输出写进文件,2>&1 是“把报错信息也一并写到同一个地方去”。很多人只写了前半截,结果程序半夜挂了,日志里干干净净什么都没有,报错全丢了,一点线索都不剩。我吃过这个亏,查一个问题查了很久,最后发现根本原因是我没记下报错。
还有 tmux。它的作用是让你的程序活在一个不依赖你这次连接的空间里。你断网、关电脑、回宿舍,它照样在跑,下次连上去接着看。
不用它的代价我很清楚。有一次我直接在连接里起了一个要跑十几个小时的训练,晚上宿舍网抽了一下,连接断了,进程跟着没了。第二天早上七点我到实验室,打开一看,昨天那一整天等于白过。那种感觉不是生气,是一种很空的、说不出话的感觉。从那以后我起长任务前的第一个动作,就是敲 tmux。
现在,我得替图形界面说几句
写到这儿,如果你以为我要劝你把鼠标扔了,那就误会了。我自己每天大量时间也在用图形界面,而且我认为在有些事情上,它是碾压式地更好。
看图、看视频、看数据分布画出来的图表,这些必须用眼睛,而眼睛需要的是画面不是文字。你让我在终端里判断一张生成出来的图片好不好看,那是自虐。
调界面、排版、做视觉相关的东西,鼠标的直接操作有一种不可替代的顺手。你手上多一分少一分,眼睛立刻给你反馈,这个闭环快得任何命令都比不了。
还有一类特别值得说:当你不知道自己想要什么的时候,图形界面强得多。
这是它一个被严重低估的优点,行话叫可发现性。图形界面把它能干的事,全都摊在菜单里给你看。你不知道一个软件能干啥,你把菜单一个个点开翻一遍,大概就有数了。你是在琳琅满目的货架之间闲逛,你会撞见你原本不知道自己需要的东西。
命令行恰恰相反。它什么都不告诉你。你想用一个工具,你必须先知道它叫什么名字。你不知道有 awk 这个东西的存在,你就永远不会用到它,哪怕它就装在你机器上。终端不会主动提示你“你可以试试这个”。
所以命令行对新手的门槛,本质上不是“难”,是“它不告诉你有什么可用”。这是一个真实的、不该被美化的缺点。那些说“命令行其实很简单,你学学就会”的人,回避了这个问题。它不是难在操作,它难在你得先知道那个词。
我自己的分界线,给你参考:
- 需要用眼睛判断的、需要探索的、一次性的,用图形界面,一点心理负担都不要有。
- 要做第二遍的、要交给别人的、要交给机器自动重复的、要留下记录的,用命令行。
这不是鄙视链,这是分工。我见过特别厉害的人,鼠标和键盘切换得毫无芥蒂,该点就点该敲就敲。反而是刚学会几个命令的人最容易开始瞧不起鼠标,那个阶段我也有过,现在回头看有点想笑。
顺便说个不太光彩的事
既然在聊好处,那也得把代价说清楚,不然是耍流氓。
命令行强大的原因和它危险的原因,是同一个:它不拦你。
图形界面删东西,会弹一个窗问你确定吗,删了还进回收站,你还有后悔的余地。命令行不问。你敲一个删除命令,回车,东西就没了,通常也没有回收站给你捞。
我干过一次。当时想清理一批用不上的模型文件,通配符写得比我以为的宽,回车之后有几个我其实还需要的文件跟着一起没了。那些文件是几天的训练结果。那天下午的心情就不用描述了。
所以有几个习惯我建议你从第一天就养上:
- 想批量删东西之前,先用
ls把同样的匹配条件跑一遍,亲眼看看它到底选中了哪些文件,确认没问题再换成删除。多花三秒,能救你好几次。 - 危险的命令,尤其涉及批量删除、覆盖、移动的,先在无关紧要的目录里试一次。
- 重要的东西,该备份就备份,代码全部交给
git管起来。 - 网上抄来的命令,看不懂的绝对不要直接回车。这一条尤其要说,因为现在你随手就能让 AI 给你生成一条命令,而它给的东西通常能用,偶尔也会给你一条你不理解的、后果很重的命令。你不用能自己写出来,但你至少得能看懂它要干什么。看不懂就先问清楚。
强大的工具默认你知道自己在干什么。这是它的尊重,也是它的风险。