小提示:本文内容较长,章节数较多,建议配合目录跳转至自己感兴趣的章节阅读。
绝大多数的读者使用Windows的过程中,难免会遇到个别问题需要求助于网络,譬如浏览器突然打不开百度首页时,此时某条资料会建议:
搜索「命令提示符」,双击打开,在弹出的窗口输入pingbaidu.com,看看能不能ping通。
有些读者在更新到Windows11后,不习惯新右键菜单,找不到换回旧菜单的选项,此时会在网上的资料中发现这样的方法:
部分读者可能对命令行有着敬而远之的心理,这不难理解。在无数的科幻电影中,黑客们对着老式主机猛敲键盘,顷刻之间改变时局,颠覆世界。
可惜,我无法传授给大家这样的本事,那些影视片段大都是唬人的。但是从另一方面考虑,命令行不是战斗机,也不是坦克,它只是家里仓库里停放许久的一辆皮卡,平时或许不会想到它,需要的时候依然皮实耐用。
然而电影里的有一幕镜头十分贴切:《黑客帝国》中Mouse小哥指着黑底绿字的屏幕说:「一个红衣女郎」,初来乍到的Neo一愣,吃惊于Mouse竟然能看懂屏幕上看似没有任何条理的文字。
在许多Windows用户的眼中,命令行是神秘的,它似乎和日常用到的各种软件应用毫无关联。但恰恰相反,命令行非常普通,它仅仅是使用应用的另外一种方式而已。
不妨用一个最常见的场景来举例:在Windows上打开Word。绝大多数人都会找到桌面的快捷方式,或者在开始菜单中搜索应用名「Word」,然后双击,轻松完成任务。
还有少部分人会知道一串快捷键:Win+Ctrl+Shift+Alt+W,按下后系统会直接打开Word,所有修饰键一起按下被称为Office键,再按下不同的字母会直接打开不同的Office套件。
当然,同时按下这么多键会让你手抽筋,更有效的做法是右键快捷方式>属性>快捷键,为这个快捷方式设定一套按键组合。此时,当焦点位于桌面时,按下设定好的按键,也能启动应用。
然而在1990年,Windows开机后并不会进入桌面,用户也没有开始菜单可以点击,只有一个界面上干净利落的MS-DOS系统等待着你的输入。
此时,键入Word,按回车,便能启动Word应用:
Windows上保留了一个类似于MS-DOS的应用——命令提示符(cmd.exe)。我们暂且不管它到底是什么,先来体验如何用命令行打开Word。在Windows上搜索「cmd」并打开该应用。
首先要做的是导航到Word应用所在的文件夹。这就像使用一些绿色软件时,因为它们安装时不会创建快捷方式,用户必须先用文件资源管理器找到exe文件所在的目录。只不过这一次我们用的是命令:cd,你可以将它理解为英文changedirectory的缩写,cd后跟上空格以及Word所在的目录(不要忘了两边的引号)回车确认执行:
回顾我们上面提到的三种打开Word的方法:
孔乙己曾向众人卖弄道:「回字有四样写法」,不同的写法实际上表达的都是同一种字。命令行、快捷键、键鼠操作其实也是同样的道理,它没有什么神秘和特别的地方。故宫有许多门,每一个门都能进入宫殿内;应用有许多种使用的方法,鼠标辅以键盘、快捷键、命令行都是和应用交互的一种途径,仅此而已。
既然都是操作应用的一种方式,那么我们为什么还放着简单快捷的图形界面不用,「返璞归真」地用命令行呢?这就要提到命令行的两大优势:功能强大、组合灵活。
仍以Word举例,假如我们需要Word不显示启动界面,且用现成的模板新建文件呢?
例如我的D盘上有一份荣誉证书模板d:\honor.dotx,我需要以此模板为基础,制作二十份不同学员的证书:
图形界面确实可以实现:为了不显示启动界面,我们需要在Word的选项中仔细搜寻一番对应的设置;从模板新建文档需要双击图标启动Word,找到D盘中的模板,最后在新建菜单中双击模板。二十份的话重复二十次即可。
在命令行中,我们仍然需要打字:同样是打开cmd并导航到Word目录,这次输入的是winword.exe/q/td:\honor.dotx,细心的读者估计已经能猜出winword.exe后的两个小尾巴的意思:q自然是指quiet,t后面既然是模板的路径,那可能代表着template,整句话就像在发号施令:
「很酷,可惜打这么多字也没简单多少。」你可能这样想。但命令行神奇之处就在于:看似它只能用在黑漆漆的命令提示符里,实际上却无处不在。
从Word示例中可以看出,常用的软件同样提供了命令调用的方式,并且可以让日常办公生活方便一点点。其实,还有许多命令行工具提供了许多图形软件所不具备的功能。
比如说我们在Bilibili上看到一个视频,非常喜欢,想要下载收藏,或者想要用在自己的作品中。目前大部分视频网站都不再提供下载为通用格式的功能。下面我们用到的是视频下载工具yt-dlp。
我建议大家把我们后续下载的小工具全部放到C:\tools或者D:\tools目录下。下载到本地若双击系统弹出警告,需要先右键文件>属性>解除锁定。
如果你尝试双击此应用,会直接「闪退」。这是正常现象,它没有图形界面,需要在命令提示符中使用。这类应用其实有个特别的名字,叫做控制台应用(ConsoleApp&TerminalApp)。
现在我们从开始菜单搜索并打开cmd.exe,这一次,我们不用cd导航到程序所在的文件夹,而是直接写出应用的全名,也就是它的完整路径。
获取应用路径的方法有两个,其一是右键文件(Windows10需要按住Shift再右键),选择「复制文件地址」,最后在cmd.exe窗口上右键点击以粘贴。
注意,在cmd中,点击鼠标右键不会呼出一套图形化菜单,Ctrl+V也不起作用。选中文本按右键是复制功能,不选中文本按右键是粘贴功能,这是以后会经常用到的技巧。
我更加推荐第二种方法:直接把文件拖动到命令提示符窗口上:
整个过程很简单对吧?我们甚至没有打过一个字母。
不过,视频下到哪去了?默认情况下,yt-dlp会在视频存在当前的目录下,也就是我们每次输入命令前都显示的那个目录,在上面就截图中,就是C:\User\Kepa,C:\User下面的这个以用户名命名的子目录又被称为Windows的用户目录,之后我们还会提到。
我不太满意默认下载的位置,想着直接下载到D盘的Videos文件夹多好。另外我还想存一份视频的封面图。就像Word示例一样。
不过不得不承认,图形界面完成不了的需求还是少数,似乎绝大多数情况下图形界面简单直观。特别在Windows这样一个图形界面做得非常完善的系统下,没必要给自己找麻烦。但微软仍然没有抛弃看似传统落后的命令行,能让微软留住开发资源的原因,是命令行那无与伦比的灵活性和自由组合的能力。
而命令行能轻松地批量处理各类任务,实现的方式之一就是脚本。
截至目前,本文已经向大家介绍了几个通过命令行形式使用的应用,每一次我都会让大家从官方网站下载,解压,然后移动到tools文件夹,再将应用所在目录添加到环境变量的Path中,用起来比普通的GUI还要更麻烦一点。有没有方法可以省心省力一点,把这些流程自动化呢?
包管理器是对于普通人来说最为实用的命令行工具。它们可以帮助你批量安装、卸载、升级PC中的应用,无需再去官网获得安装包。对于前面的例子中,需要手动添加进环境变量的应用,包管理器也会自动帮你处理好。
Windows平台主流的三个包管理器中,
值得一提的是,除了Scoop有社区维护的国内镜像,其他平台的包管理都会用到服务器位于大陆之外的网络资源,因而默认情况下载速度不太理想。这一小节会以Chocolatey为例介绍包管理器的各种用法。
下面需要用choco来搜索一下我们之前用到过的几个小工具。搜索ytp-dl的命令是:
一些读者可能非常在意空格问题。空格只是其分隔作用,无论有多少都无所谓。比方说,我想查看youtube-dl的具体信息,执行CHOCOinfoYOUTUBE-DL也是完全没问题的。
安装的命令是chocoinstall,卸载是chocouninstall,升级为chocoupgrade。我们还能用chocoexport将所有安装的应用导出为列表,再用chocoimport导入重装:
Chocolatey其实提供了GUI版本(chocoinstallChocolateyGUI-y),读者可以尝试一番,但想必不过多久就会用回命令行,毕竟CLI的资源占用和流畅度一定会比封装后的GUI好上不少。
前文中我们介绍了许多命令行工具,但在使用这些工具之前,我们都要打开cmd或PowerShell,它们到底是什么?
之前我们提到了Windows的前身,MS-DOS,这是一个只能通过命令行操作的古老系统。而所谓系统,本质上也是一个软件,但通常的软件是系统和用户的中介,例如我们没办法不开机就使用Office办公套件,用Word编辑一个文档必须先让Windows启动。
但系统中的某些部分不一样,它直接和硬件打交道,用户和软件都通过系统这个中介来使用硬件资源完成任务。在系统,软件,用户这三个角色中,系统中负责调度硬件的那一部分离核心最近,地位最核心,因而有了一个形象的名字:内核(Kernel)。
类似于一个坚果,有内核必然有外壳。最早人们既然用命令行的方式和系统交互,那么能运行命令的东西也自然就成了壳(shell)。
Windows上的cmd、PowerShell是shell的一种。此外,Linux和macOS上有各种各样以sh结尾的应用,例如bash、zsh、fish以及csh,其中的sh就是shell的缩写。所以这些单词会有三种读法:
shell还有一个更加形象的名字:命令行解释器。我们已经遇到过一些命令:cd会进入某个目录、del能删除文件。这些命令很大程度上从自然语言精简而来,显然,操作系统并不能理解人类的语言,而shell把cd、del等命令翻译成计算机能读懂的语言,它在用户和系统间充当了翻译官的角色。
因而也可以想见,不同的shell是不同的语言之间翻译官。一条命令可以在PowerShell中执行成功,但cmd却可能会报错。例如,在PowerShell中执行ls(list的简称)可以列出当前目录下的所有条目,但cmd却不认识这个命令:
bash、zsh等Unix-like系统上的shell和PowerShell更是有天壤之别,虽然有少部分知识是相通的,但Windows上学习了PowerShell后,仍然需要再系统地学一遍其他平台的shell操作,反之亦然。
不过虽然这么说,仔细观察不难发现,cmd和PowerShell的窗口真是太像了,如果没有菜单栏的图标,你几乎看不出它们的区别。
之所以会这样,是因为我们看到的不是shell本体,而是叫做Windows控制台(conhost.exe)的应用,它的背后藏着真正的shell.
Windows控制台们有着另一个名字:终端仿真器(terminalemulator),简称终端。
不妨做一个类比:微软推出的Edge浏览器和Google的Chrome浏览器基于同一个开源项目:Chromium。我们在地址栏上输入同一个网址后,两个浏览器都会展示同样的网页,这是因为两个浏览器负责渲染网页的核心是一样的。但Edge和Chrome的右键样式、设置页面、各种按钮等外在却完全不同。
下面的演示中,我会一直使用这个更加现代美观的Windows终端。没有安装的读者,可以从MicrosoftStore中搜索下载。之后,在Windows设置>隐私和安全性>开发者选项中,将其设置为默认终端:
综上所述,shell和终端的定义和区别在于:shell将用户的输入解释成计算机能够理解的语言,是运行各类命令的地方,不同的shell语法不同;而终端是shell的可视化界面,掌管着输入和输出,我们可以用Windows终端来替代Windows控制台以获取更好的体验。
搞清楚了不同终端间的区别,我们再来仔细看下终端中运行的不同命令间的区别。
在Windows上cmd和PowerShell是两个完全不同的翻译官,一条命令可以在PowerShell中执行成功,但cmd却可能会报错。
一些读者可能有疑问:那为什么很多工具既可以在cmd上运行,也能在PowerShell上运行,并且用法完全一致呢?
事实上,这些工具不只在Windows平台语法相同,在Linux和macOS的shell中也是一样的。它们不依赖于shell而存在,被称为外部命令,与之对应的,是shell自带的命令,被称为shell命令。
此外还有一部分跨平台的命令行工具既非外部命令,也非shell命令,它们其实是脚本。开发者为不同的shell写了不同的脚本文件来保证使用体验一致。
回忆一下第一篇中我们提到的一些例子。ping、Word、yt-dlp、adb、notepad等等命令,当时我们是在cmd中运行的,你可以尝试用PowerShell来执行这些命令,可以发现语法、功能都完全一致。
原理很简单。打个比方,Windows和macOS是两个系统操作逻辑大相庭径,但两个系统上的Chrome浏览器按钮、菜单、功能大致是一样的。同样的道理,yt-dlp等外部命令是以可执行程序(exe文件)形式存在的,命令的参数和功能已经由第三方开发人员预先设计好,无论是什么shell都不会影响它们的用法。
我们可以用where.exe程序证实上面的说法,它会返回一个外部命令的真实路径。例如,在cmd或者PowerShell输入where.exeping,终端会出现ping.exe的路径:
那如何理解shell命令呢?外部命令之间没有什么联系,就像Notepad和Word之间没有关系一样;但shell命令类似于Word这个应用中的一个个小功能,它们是由同一个开发商为了一个大的目标,用一套规整的逻辑设计出来的。例如,cmd自带的所有命令的参数都用/标记,而PowerShell命令的参数则是由-标记的。还记得之前用adb禁用应用的命令吗?
adbshellpmdisable-usercom.tencent.mm有没有想过为什么它这么长?原因在于这行代码做了两件事,adbshell负责进入adb提供的shell;pmdisable-user才是禁用应用的命令,adb提供的shell中,其他的命令长得都和pmdisbale-user差不多:
搞清楚了外部命令和shell命令,就该好好学习下命令行的语法。
应用有许多种使用的方法,鼠标辅以键盘、快捷键、命令行都是和应用交互的一种途径。
以手机App为例,所有手机应用都在一套统一的交互逻辑的框架下:
只要理解了点、按、滑这三个基本操作,不用任何人教我们也能掌握一个新APP的基本用法。桌面端的应用交互也有类似的逻辑,鼠标左键、右键、中键不正是对应着确认、更多和滑动吗?反过来说,你会觉得各种快捷键记起来很麻烦,背后的原因是不是快捷键背后缺少一套统一的设计逻辑呢?
这就是第一篇所说的「和应用交互的途径」的本质。掌握了点按滑就会使用手机的各种应用,那学会了什么样的逻辑,就学会了所有的命令行应用呢?
我们不妨把之前用过的几个命令写在一起:
命令名动作参数1参数2参数3……shell环境下各种命令都能抽象为上面的结构,只不过它们在某些字符的写法和顺序上有所不同,一些命令可能没有后两个部分。我们暂且把命令间的区别放一边,先逐个部分解释其中的共性。
第一部分是命令名。无论使用什么命令,都必须先叫出它的名字。就像分配任务时,必须先指定负责人一样。对于外部命令而言,命令名就是外部应用的文件名。在前面的学习中,我们既看到过简短如notepad、choco的应用名称,也认识到:如果应用所在路径没有加进环境变量,就必须写出应用的完整路径,否则shell就会报错:
该输入什么命令名,取决于应用开发者给他的应用起了什么名字,我们能用where.exe看到外部命令的具体路径。不过那些自行下载到本地的应用,我们完全可以把它们改成自己喜欢的名字,下图中我就把之前用到过的yt-dlp.exe重命名为yt.exe,执行起来也没有任何问题:
和类Unix系统不同,Windows文件系统不区分大小写,因而应用名也不区分大小写。ping、PING乃至piNG都是同一个应用:
如果一个应用的完整路径含有空格,必须加双引号。因为一行命令的不同部分之间就是用空格分隔的,如果不加引号,shell就会把它当作几份分别解析。此外务必记住,和cmd不同,PowerShell在执行加引号的命令时,前面必须加&(见下图第三条命令),背后的原因我们之后会学到:
第二部分是动作。如果说命令名对应着一句话的主语的话,那么动作部分就相当于谓语和宾语。不同的命令的动作部分可能是类似的,例如scoopinstallyt-dlp和chocoinstallyt-dlp都是安装yt-dlp的意思。要想理解一行命令的功能,第一和第二部分是关键,例如Chocolatey还原代理的命令:
chococonfigunsetproxy命令名是choco,后面都是动作部分,读起来像是一句精炼过的句子:
真正的难点在于第三部分参数,它的作用是详细规定一个动作要如何完成。很多情况下,学习命令行工具就是在学参数。一个命令可以有几十个参数,它们看似复杂,实际也有规律可循。
参数部分由特殊符号开头。本节一开始列出的四个命令,它们的参数前面是-(减号)、--(两个减号)或/(斜杠)这三种特殊符号,后面则是相对贴近自然语言的字母或者单词:virtualdesktop/w/right的作用切换到右侧的桌面,参数right指向右,参数w是Wrap的缩写,表示当切换到最右侧的桌面时,绕回第一个桌面。
在下面这行命令中:
powershell.exe-nologo-fileD:\tools\init.ps1
我们还能发现两类不同参数:-fileD:\tools\init.ps1是常规参数,其结构是参数名参数值,也就是说D:\tools\init.ps1是file的具体值。对于常规参数而言,一旦我们写了参数名,往往需要为它指定一个合适的数值:
参数名和参数值的连接方式因应用而异。大多数命令用的是空格,不过也有用=或者:的案例。譬如用choco锁定应用(不进行更新)的命令:
chocopinadd-name=<应用名>
这里用的就是=号。
参数的大小写和命令名不同,是由应用开发者控制的。-f和-F极有可能是两个不同的参数,因而在输入参数的时候务必小心。
了解完命令的三大主要成分,在键入命令时你应该会更有信心了。但理解了命令行的语法并不足以帮助我们掌握陌生的命令,我们还需要明确地知道一个命令可以加哪些动作,有哪些参数。
而在我们接触了这么多命令行工具之后,不难发现,在命令名动作参数这个组合中,外部命令的前两部分都大同小异,但参数部分则各有特点。根据这些特点,我们可以将外部命令分为三类。了解完这三种「模具」,你便能更快地掌握新的外部命令。
计算机发展过程中,在Unix时代几个最为流行的shell——sh(bin/sh)、Bash(/bin/bash)影响下,命令行的最初规范逐步确立,之所以Linux、macOS等Unix-like系统上的各类shell命令基本一致,便是因为它们或多或少都遵循着这些习惯。
现代的开发者们在设计自己的应用时,常常倾向于和类Unix系统上的shell命令风格保持一致。因而,Unixsh风格的外部命令非常常见。比如说我们刚刚用到的cURL,通过文档观察其语法和参数:
命令的特点是:
以上四点是所有Unixsh风格命令的共有特征,如果碰到了这类命令,使用command--help大概率能调出其文档。
不只是cURL,我们用过的npm、yt-dlp等大部分应用属于此类风格,比如说当初我们用yt-dlp下载视频的命令是:
yt-dlp
不过有时候你会看到这类命令的短横线后跟了不只一个字母,比如说curl-fsSL、git-am,这并没有和Unixsh风格冲突,而是同时指定多个短参数的简单写法:curl-fsSL等同于curl-f-s-S-L。
从各种意义上,Windows都不遵循许多类Unix系统奉为圭臬的种种习惯。cmd是微软从MS-DOS基础上拓展而来的shell,这也造就了Unixsh风格之外的Windowscmd风格,它的典型例子就是cmd本身了:
其特征是:
调出它们的文档的方法是command/。除了cmd,之前我们用过的Word、VirtualDesktop都属于此类。实际上,大部分Windows预置的外部命令,以及专门为Windows写的应用一般都遵循这类风格,例如Windows自带的电源管理小工具,powercfg.exe:用它来生成一份电池使用报告的命令是:powercfg.exe/BATTERYREPORT,将参数小写也是没问题的:
相较于一板一眼的Unixsh风格,这类的命令设计得非常宽松,一些命令支持省略参数前的/符号,或者用-代替,这也是为什么大家能在网络上看到同一个命令的各种写法。我仍然建议大家统一地使用/,因为并非所有应用都支持此特性。
第三种风格的命令更好理解,其特点是:
查阅这类命令文档的方法一般是command-help,可以缩写为-h,少数跨平台的应用倾向于使用这种风格,前文展示过的PowerShell、magick都属于此类:
这是最简单的一类命令,我们只要记住它的参数是由-引导的即可。但它们的缺点是命令写起来往往很长。