作为 2024 年五一「生产力超频」系列目优惠活动的一部分,本期设置为限时免费,欢迎观看。我们将在 5 月 1 日至 7 日,为热门付费栏目「生产力超频」全系列设置七折优惠;同时,我们将每天从不同教程中选出一篇,设为限时免费。希望这些内容和优惠为你助力,开启一个效率和技能「超频」的五月。进一步了解
今天的限时免费内容来自《Windows 命令行实用手册》,带你掌握 PowerShell 命令的基本语法及风格。本栏目从完全新手的角度出发,通过使用一个个命令行工具,带读者逐步掌握其背后的概念。如果你已经了解了基本概念和用法,栏目中也准备了能进一步挖掘 Windows 命令行潜力的进阶内容。栏目原价 59 元,折后价 41.30 元(节省 17.70 元)。前往购买
读到这篇文章的时候,你已经理解了 shell 和终端的概念,并且认识到 shell 命令和外部命令的显著区别,此外,你还了解到命令行可以配合快捷方式、任务计划程序、AHK 等各类应用,使它们更加灵活方便。
同时,在前面两篇文章中,我带着大家操作了 ytp-dl、adb 等十几个命令行应用,大家照着文章给出的代码,也实际地完成了不少任务,但相信你一定不满足于文章列出的例子,想要自己学到更多的命令。
所谓「授之以鱼不如授之以渔」,这篇文章会教给大家自行探索命令行世界的方法,快速掌握任何新的命令行应用,同时帮助初学者准确地定位输入命令时的错误。本文主要解答四个问题:
仔细琢磨的话,「学习使用命令行」这个话题似乎有些奇怪。因为命令行应用也是应用程序,类比来看,经常使用手机的用户很少会问「如何使用淘宝」、「如何使用微信」等问题。
可命令行偏偏不同,如果我不在第一篇文章中告诉大家 Word 可以加 /t
参数,你可能从来没想过 Word 可以这么用。因此有一种观点认为,CLI 最大的缺陷就是「可发现性」差。
但事实并非完全如此。之所以许多人会觉得命令行难,是因为他们习惯了另外一种逻辑。还记得第一篇文章中我如何阐述 CLI 作用的吗?
应用有许多种使用的方法,鼠标辅以键盘、快捷键、命令行都是和应用交互的一种途径。
以手机 App 为例,所有手机应用都在一套统一的交互逻辑的框架下:
只要理解了点、按、滑这三个基本操作,不用任何人教我们也能掌握一个新 APP 的基本用法。桌面端的应用交互也有类似的逻辑,鼠标左键、右键、中键不正是对应着确认、更多和滑动吗?反过来说,你会觉得各种快捷键记起来很麻烦,背后的原因是不是快捷键背后缺少一套统一的设计逻辑呢?
这就是第一篇所说的「和应用交互的途径」的本质。掌握了点按滑就会使用手机的各种应用,那学会了什么样的逻辑,就学会了所有的命令行应用呢?
和 GUI 不同,命令行中,我们就像写文章一样是通过输入字符来完成任务的,因而使用命令行的逻辑表现为语法(Syntax)。就像所有手机 App 都能点、按、滑一样,无论是 PowerShell、cmd 还是 Bash,所有运行在 CLI 上的命令都遵守着一些共同的语法规范。
我们不妨把之前用过的几个命令写在一起:
yt-dlp https://www.bilibili.com/video/BV1jS4y1o7Fc --output D:\Videos\sspai_test.mp4 --write-thumbnail
choco search youtube-dl -r -e
VirtualDesktop11 /w /right
powershell -nologo -file D:\tools\init.ps1
尽管它们功能、用法大相径庭,但命令的构成却出奇地一致:命令名,动作,参数,它们之间以空格分隔。命令行的语法可以总结为:
命令名 动作 参数1 参数2 参数3 ……
shell 环境下各种命令都能抽象为上面的结构,只不过它们在某些字符的写法和顺序上有所不同,一些命令可能没有后两个部分。我们暂且把命令间的区别放一边,先逐个部分解释其中的共性。
第一部分是命令名。无论使用什么命令,都必须先叫出它的名字。就像分配任务时,必须先指定负责人一样。对于外部命令而言,命令名就是外部应用的文件名。在前面的学习中,我们既看到过简短如 notepad
、choco
的应用名称,也认识到:如果应用所在路径没有加进环境变量,就必须写出应用的完整路径,否则 shell 就会报错:
该输入什么命令名,取决于应用开发者给他的应用起了什么名字,我们能用 where.exe
看到外部命令的具体路径。不过那些自行下载到本地的应用,我们完全可以把它们改成自己喜欢的名字,下图中我就把之前用到过的 yt-dlp.exe
重命名为 yt.exe
,执行起来也没有任何问题:
和类 Unix 系统不同,Windows 文件系统不区分大小写,因而应用名也不区分大小写。ping
、PING
乃至 piNG
都是同一个应用:
如果一个应用的完整路径含有空格,必须加双引号。因为一行命令的不同部分之间就是用空格分隔的,如果不加引号,shell 就会把它当作几份分别解析。此外务必记住,和 cmd 不同,PowerShell 在执行加引号的命令时,前面必须加 &
(见下图第三条命令),背后的原因我们之后会学到:
第二部分是动作。如果说命令名对应着一句话的主语的话,那么动作部分就相当于谓语和宾语。不同的命令的动作部分可能是类似的,例如 scoop install yt-dlp
和 choco install yt-dlp
都是安装 yt-dlp 的意思。要想理解一行命令的功能,第一和第二部分是关键,例如 Chocolatey 还原代理的命令:
choco config unset proxy
命令名是 choco
,后面都是动作部分,读起来像是一句精炼过的句子:
choco 配置 取消设置 代理
一些应用本身功能单一,命令名本身的意指就非常明确了,那么它就不需要第二部分。譬如第二篇文章中提到的 Chrome,用命令行的方式调用它的时候,Chrome 唯一的作用就是打开浏览器。
真正的难点在于第三部分参数,它的作用是详细规定一个动作要如何完成。很多情况下,学习命令行工具就是在学参数。一个命令可以有几十个参数,它们看似复杂,实际也有规律可循。
参数部分由特殊符号开头。本节一开始列出的四个命令,它们的参数前面是 -
(减号)、--
(两个减号)或 /
(斜杠)这三种特殊符号,后面则是相对贴近自然语言的字母或者单词:virtualdesktop /w /right
的作用切换到右侧的桌面,参数 right
指向右,参数 w
是 Wrap
的缩写,表示当切换到最右侧的桌面时,绕回第一个桌面。
在下面这行命令中:
powershell.exe -nologo -file D:\tools\init.ps1
我们还能发现两类不同参数:-file D:\tools\init.ps1
是常规参数,其结构是 参数名 参数值
,也就是说D:\tools\init.ps1
是 file
的具体值。对于常规参数而言,一旦我们写了参数名,往往需要为它指定一个合适的数值:
参数名和参数值的连接方式因应用而异。大多数命令用的是空格,不过也有用 =
或者 :
的案例。譬如用 choco
锁定应用(不进行更新)的命令:
choco pin add -name=<应用名>
这里用的就是 =
号。
常规参数之外,-nologo
被称为开关参数(switch parameter)。这类参数只有是和否两种状态。如果我们不写 -nologo
,那么 PowerShell 就会显示版权信息,反之则会隐去相关信息。choco
命令中的 r
和 e
也是类似的道理。
参数的大小写和命令名不同,是由应用开发者控制的。-f
和 -F
极有可能是两个不同的参数,因而在输入参数的时候务必小心。
了解完命令的三大主要成分,在键入命令时你应该会更有信心了。但理解了命令行的语法并不足以帮助我们掌握陌生的命令,我们还需要明确地知道一个命令可以加哪些动作,有哪些参数。
如果诸位有过自行清洗大型家电以及保养汽车的需求,那么家电的说明书和汽车的保养手册一定是参考资料之一。想要知道一个命令的动作、参数,最优解也是阅读命令行工具自带的说明书,计算机领域我们更愿意称之为文档。
那么调出命令行工具的文档呢?联系上一节的内容,「帮助」一词作为关键字可能出现在动作或者参数部分中:
command help # 命令名 + 动作(help)
command /? # 以 / 开头的参数
command /h # 以 / 开头的参数
command -h # 以 - 开头的参数
command --help # 以 -- 开头的参数
以上五个命令逐个试下来,能调出绝大多数命令的文档。比如说,choco
和 scoop
的文档用的是命令名 + help 的形式查阅;cmd
的帮助文档可以用 cmd /?
调出;第二篇文章末尾提到的 VScode 命令的帮助文档是用 code -h
:
一些命令,比如说 yt-dlp
,运行失败后会直接告诉你如何调出帮助文档:
yt-dlp --help
这些文档就像一本字典一样,详细地告诉你命令的每一个用法以及每一个参数的含义。从头看到尾并不推荐。很多人都会用 Photoshop,但为了简单修图而去学习 Photoshop 的所有选项并不明智。我们需要有目的地看文档,着重把握三个要点:
请大家使用包管理器下载 Node.js,它包含了一个简单的命令行工具 npm
,可以安装第三方的 JavaScript 包。下面我们以这个场景为例,利用自带的文档找到全局安装 fanyi
包的命令,这是一个用于终端下的中英翻译工具。
首先自然是查阅 npm 的文档,逐一尝试本节开头列出的五个命令,发现 npm help
就能调出文档:
我们需要的是安装(install)一个工具,恰巧对应了文档中对 npm install
的解释。不过这行说明过于简短,再往下看,能发现 npm <command> -h
命令,功能是展示某个命令的帮助文档。所以我们需要再执行 npm install -h
。顺便一提,要是你觉得用鼠标滚动太麻烦,在 PowerShell 中可以尝试 Ctrl + L
快捷键,它会将当前输入行置顶:
这次展示的文档就更加详细了,它明确告诉我们用 npm 安装一个工具的具体语法是:
npm install [<package-spec> ...]
这行表述用到了两对特殊的符号,[]
和 <>
,在命令行工具的文档中,它们有固定的意义,[]
代表可选成分,<>
代表必选成分。也就是说,npm install
后面不加任何东西也能执行成功,但如果要添加什么,必须填上 package-spec,也就是包名。
因为目的是全局安装,就直接在文档中寻找意义近似于全局的参数。Windows 终端也有查找功能,我们可以用 Ctrl + Shift + F
调出:
果不其然让我们找到了 [-g | --global]
参数。方框后中两个参数分布在|
(竖杠)左右,这或意味着前后两个参数互斥,或意味着两者功能相同,因而,全局安装 fanyi 的命令应该是:
npm install fanyi -g
## 如果下载慢,请改用下面这行命令调用国内镜像。
npm install fanyi -g --registry https://registry.npm.taobao.org
在参数部分的后面,npm 还提示我们能运行 npm help install
能获得更多的信息,这会用浏览器打开官网的文档,里面有每个参数更详细的解释。
上一步中,我们成功地安装了 fanyi
,npm 会帮我们处理好环境变量的问题。大家不妨自己尝试着调出 fanyi
的文档,看看如何用它在不发音的情况下翻译一个单词。
经过一番尝试,你最终会发现能用 fanyi -h
或者 fanyi --help
调出其文档:
说实话,它的文档写得并不好,具体语法部分和其他部分有冲突,此时示例就非常有用了。列出的三个例子都是用 fanyi
命令名直接加需要处理的词句,文档中又列出了 -S
(大写的 S)参数,其功能不发音。之前提到过有的命令参数区分大小写在这个命令也有体现,小写的 -s
参数意味着发音。用它来翻译「kepa」这个单词的命令是:
fanyi kepa -S
当然,除了阅读应用自带的文档,网络永远是我们的好帮手。对于一些命令而言,网络也是获取它们详细用法的唯一渠道。
想要得到命令的具体用法,最好的去处一定是应用的发布处,例如开发者的网站或者 GitHub。比如说我想知道 Word 支持哪些参数。因为 Word 并非为在命令行中使用而设计,所以我们是不能用 winword help
之类的命令调出其文档的,此时,就要在搜索引擎中检索关键词:「microsoft word cli parameter」,输入关键词会比「how to use word in terminal」之类的句子更高效:
上图的三个结果中,排名第一的是 Word 的开发商微软的网站,所以那里大概率就有最权威的答案:
网友发布的帖子同样有参考价值。命令自带的文档也好,官网给的详细说明也好,都是教科书一般的存在,尽管事无巨细,但少了些针对性。例如,第二篇中提到的图片处理工具 magick,它的文档和官网给的说明多达数十页。假如我只想用它来将图片转换为 jpg,并且保留原来的文件名,倒不如「抄网友的作业」,检索「magick convert to jpeg same name」:
排名第一的是知名的 IT 技术类问答社区 stack overflow,简单浏览就能得到想要的答案:
不过「抄作业」也要建立在对命令基本的了解之上。网页中给的命令是 mogrify -format png *.psd
,其作用是将 psd 转换为 png,如果你尝试直接运行,shell 会报错,你必须事先知道 magick 的基本语法是 magick tools ……
,所以我们需要的的命令应该是:
magick mogrify -format jpeg <path>
这同时是本文写作的目的,理解了命令行的基本规范,简单翻阅了命令的文档,复制粘贴才会有意义。
前面介绍了两种查阅命令行说明书的方法:调用自带的文档和网络搜索,一开始阅读这些文档可能有些吃力,但随着积累越来越多,我们能够从中找到一些共性,举一反三。这时候,仅需稍加提示,我们就能直接猜出命令,而最好的提示就是命令的具体使用示例。因此,真的有人做了这样一个网站,收录了大量的命令行工具的具体示例,域名也非常好记:shell 的小抄:https://cheat.sh/
网站首页写着使用方法:执行 curl cheat.sh/<command>
或者缩写版 curl cht.sh/<command>
。cURL(choco install curl -y
)是用于发送和处理网络请求的命令行工具,安装此工具后,假如我想知道浏览器 chromium
命令的具体用法,只需执行 curl.exe cht.sh/chromium
(PowerShell 5 请不要省略 curl 后的 .exe
):
数行文档,基本涵盖了各种常见的使用情况,虽然不能替代官方的说明书,但它提供的「太长不读」版本着实能省下不少时间。
而在我们接触了这么多命令行工具之后,不难发现,在 命令名 动作 参数
这个组合中,外部命令的前两部分都大同小异,但参数部分则各有特点。根据这些特点,我们可以将外部命令分为三类。了解完这三种「模具」,你便能更快地掌握新的外部命令。
计算机发展过程中,在 Unix 时代几个最为流行的 shell —— sh(bin/sh
)、Bash(/bin/bash
)影响下,命令行的最初规范逐步确立,之所以 Linux、macOS 等 Unix-like 系统上的各类 shell 命令基本一致,便是因为它们或多或少都遵循着这些习惯。
现代的开发者们在设计自己的应用时,常常倾向于和类 Unix 系统上的 shell 命令风格保持一致。因而,Unix sh 风格的外部命令非常常见。比如说我们刚刚用到的 cURL,通过文档观察其语法和参数:
命令的特点是:
-
或者 --
开头;-
后接短参数,即一个字母,--
后接长参数,即完整的单词,多个单词由 -
连接。前者往往是后者的简写形式;=
连接;以上四点是所有 Unix sh 风格命令的共有特征,如果碰到了这类命令,使用 command --help
大概率能调出其文档。
不只是 cURL,我们用过的 npm、yt-dlp 等大部分应用属于此类风格,比如说当初我们用 yt-dlp 下载视频的命令是:
yt-dlp <url> --output D:\Videos\sspai_test.mp4 --write-thumbnail
命令的文档告诉我们参数 --output
有一个简写形式 -o
,因此,它和下面的命令是等价的:
yt-dlp <url> -o D:\Videos\sspai_test.mp4 --write-thumbnail
又因为 Unix-like 风格的命令区分大小写,所以千万不要写成了 yt-dlp <url> -O ……
。
不过有时候你会看到这类命令的短横线后跟了不只一个字母,比如说 curl -fsSL
、git -am
,这并没有和 Unix sh 风格冲突, 而是同时指定多个短参数的简单写法:curl -fsSL
等同于 curl -f -s -S -L
。
从各种意义上,Windows 都不遵循许多类 Unix 系统奉为圭臬的种种习惯。cmd 是微软从 MS-DOS 基础上拓展而来的 shell,这也造就了 Unix sh 风格之外的 Windows cmd 风格,它的典型例子就是 cmd 本身了:
其特征是:
/
符号,其后既可以是字母,也可以是单词;:
连接。调出它们的文档的方法是 command /?
。除了 cmd,之前我们用过的 Word、VirtualDesktop 都属于此类。实际上,大部分 Windows 预置的外部命令,以及专门为 Windows 写的应用一般都遵循这类风格,例如 Windows 自带的电源管理小工具,powercfg.exe:用它来生成一份电池使用报告的命令是:powercfg.exe /BATTERYREPORT
,将参数小写也是没问题的:
相较于一板一眼的 Unix sh 风格,这类的命令设计得非常宽松,一些命令支持省略参数前的 /
符号,或者用 -
代替,这也是为什么大家能在网络上看到同一个命令的各种写法。我仍然建议大家统一地使用 /
,因为并非所有应用都支持此特性。
第三种风格的命令更好理解,其特点是:
-
开头,-
后可以是单词或字母;查阅这类命令文档的方法一般是 command -help
,可以缩写为 -h
,少数跨平台的应用倾向于使用这种风格,前文展示过的 PowerShell、magick 都属于此类:
这是最简单的一类命令,我们只要记住它的参数是由 -
引导的即可。但它们的缺点是命令写起来往往很长。
随着学习的深入,我们接触到的命令行工具越来越多,大家可能会有这样的感触:「一些命令打起来很麻烦,如果能简化一下就好了」。确实如此,就以前面用过的两行命令为例:
yt-dlp <url> --output D:\Videos\sspai_test.mp4 --write-thumbnail
npm install <package> -g --registry https://registry.npm.taobao.org
第一行命令中的 --output
参数功能是将下载的视频存到固定的文件夹,如果我要下载十几个视频,每一次都打一遍存储路径是不是过于繁琐了;类似的,难道每一次安装 npm 包都要写一遍 --registry
参数吗?
大家可以回想一下在 GUI 中我们是怎么做的:使用手机 App 时,浏览一遍设置面板中有哪些选项,按自己的习惯调整后,这样做才能用得舒服一些。换句话说,GUI 的某些设置是可以固化下来的。其实命令行工具也有同样的设计。
一些命令行工具提供了单独的 config
动作,我们执行一遍后,设置就能永久生效。例如,为 npm 全局配置国内源的命令为:
npm config set registry https://registry.npm.taobao.org
将 choco 的下载路径调整为 D:\Downlaods 的命令为:
choco config set cacheLocation $home/Downloads
在使用这些命令前大家可以仔细阅读文档,看一看有没有相应的设置:
更多情况下,命令的设置藏得比较隐蔽,我们能在其官网找到相关的说明,以 yt-dlp 为例,官网提到,可以在 %APPDATA%/yt-dlp
目录下新建一个 config 文件,将常用的配置写入其中:
假如我们想让 yt-dlp 下载的视频始终存放在 D:\Videos
文件夹下,并且设置代理 127.0.0.1:3128
,就新建一个配置文件,然后写入:
# Use this proxy
--proxy 127.0.0.1:3128
# Save all videos under YouTube directory in your home directory
-o D:/Videos/%(title)s.%(ext)s
如此操作后,我们以后就能直接用 ytp-dl <url>
的方式下载视频了。
事实上,config
动作的实际做的也是修改了存放在某处的文件。npm 的文件是用户目录下的 .npmrc
,choco 的则是 ProgramData\chocolatey\config\chocolatey.config
:
我们习惯于称这类文件为配置文件,因为它们往往以点号开头,英文资料中多用 dotfile 来指代。这和 GUI 应用的设置界面是同样的道理,只不过一个是有图形化界面,另一个只是纯文本而已。GUI 的设置入口多种多样,命令行工具的配置文件的路径也多种多样,Windows 环境下,开发者一般会选择将其设计在如下三个目录下:
C:\User\<UserName>\
,可能默认被隐藏;AppData
目录:~\AppData\Roaming\
或者 ~\AppData\Local
下的应用开发者亦或应用名文件夹;C:\ProgramData
目录:此文件夹为隐藏状态。本文是有关外部命令的最后一篇文章,解答了前两篇文章留下的诸多问题:
命令名 动作 参数1 参数2 ...
;curl cht.sh/<command>
可以帮你省下不少时间;--
和 -
引导参数的 Unix sh 风格,参数以 /
开头的 cmd 风格,以及最为简单的 PowerShell 风格;学习完这一篇文章,绝大多数外部命令都难不倒你了,同时如果你回过头去看第一篇和第二篇文章中的那些例子,也应该会有更深的理解。
下一篇文章会从操作文件这个场景切入,讲述 shell 命令。它的使用场景自然也不只是和系统交互,和外部命令不同,shell 命令有着「胶水」一般的效果,我们将不再局限于一行一行死板地执行命令,完成更加复杂的任务。
© 本文著作权归作者所有,并授权少数派独家使用,未经少数派许可,不得转载使用。