3

3. 掌握命令的基本语法及风格

 1 week ago
source link: https://sspai.com/post/78248
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

3. 掌握命令的基本语法及风格

作为 2024 年五一「生产力超频」系列目优惠活动的一部分,本期设置为限时免费,欢迎观看。我们将在 5 月 1 日至 7 日,为热门付费栏目「生产力超频」全系列设置七折优惠;同时,我们将每天从不同教程中选出一篇,设为限时免费。希望这些内容和优惠为你助力,开启一个效率和技能「超频」的五月。进一步了解

今天的限时免费内容来自《Windows 命令行实用手册》,带你掌握 PowerShell 命令的基本语法及风格。本栏目从完全新手的角度出发,通过使用一个个命令行工具,带读者逐步掌握其背后的概念。如果你已经了解了基本概念和用法,栏目中也准备了能进一步挖掘 Windows 命令行潜力的进阶内容。栏目原价 59 元,折后价 41.30 元(节省 17.70 元)。前往购买


读到这篇文章的时候,你已经理解了 shell 和终端的概念,并且认识到 shell 命令和外部命令的显著区别,此外,你还了解到命令行可以配合快捷方式、任务计划程序、AHK 等各类应用,使它们更加灵活方便。

同时,在前面两篇文章中,我带着大家操作了 ytp-dl、adb 等十几个命令行应用,大家照着文章给出的代码,也实际地完成了不少任务,但相信你一定不满足于文章列出的例子,想要自己学到更多的命令。

所谓「授之以鱼不如授之以渔」,这篇文章会教给大家自行探索命令行世界的方法,快速掌握任何新的命令行应用,同时帮助初学者准确地定位输入命令时的错误。本文主要解答四个问题:

  • 学习使用命令行,最重要的是学会什么?
  • 如何查看命令行应用的文档?
  • 有哪些类型的命令行应用?
  • 如何像设置 GUI 应用一样设置命令行工具?

理解命令行的语法

仔细琢磨的话,「学习使用命令行」这个话题似乎有些奇怪。因为命令行应用也是应用程序,类比来看,经常使用手机的用户很少会问「如何使用淘宝」、「如何使用微信」等问题。

可命令行偏偏不同,如果我不在第一篇文章中告诉大家 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 环境下各种命令都能抽象为上面的结构,只不过它们在某些字符的写法和顺序上有所不同,一些命令可能没有后两个部分。我们暂且把命令间的区别放一边,先逐个部分解释其中的共性。

第一部分是命令名。无论使用什么命令,都必须先叫出它的名字。就像分配任务时,必须先指定负责人一样。对于外部命令而言,命令名就是外部应用的文件名。在前面的学习中,我们既看到过简短如 notepadchoco 的应用名称,也认识到:如果应用所在路径没有加进环境变量,就必须写出应用的完整路径,否则 shell 就会报错:

1

该输入什么命令名,取决于应用开发者给他的应用起了什么名字,我们能用 where.exe 看到外部命令的具体路径。不过那些自行下载到本地的应用,我们完全可以把它们改成自己喜欢的名字,下图中我就把之前用到过的 yt-dlp.exe 重命名为 yt.exe,执行起来也没有任何问题:

1

和类 Unix 系统不同,Windows 文件系统不区分大小写,因而应用名也不区分大小写。pingPING乃至 piNG 都是同一个应用:

1

如果一个应用的完整路径含有空格,必须加双引号。因为一行命令的不同部分之间就是用空格分隔的,如果不加引号,shell 就会把它当作几份分别解析。此外务必记住,和 cmd 不同,PowerShell 在执行加引号的命令时,前面必须加 &(见下图第三条命令),背后的原因我们之后会学到:

1

第二部分是动作。如果说命令名对应着一句话的主语的话,那么动作部分就相当于谓语和宾语。不同的命令的动作部分可能是类似的,例如 scoop install yt-dlpchoco install yt-dlp 都是安装 yt-dlp 的意思。要想理解一行命令的功能,第一和第二部分是关键,例如 Chocolatey 还原代理的命令:

choco config unset proxy

命令名是 choco,后面都是动作部分,读起来像是一句精炼过的句子:

choco 配置 取消设置 代理

一些应用本身功能单一,命令名本身的意指就非常明确了,那么它就不需要第二部分。譬如第二篇文章中提到的 Chrome,用命令行的方式调用它的时候,Chrome 唯一的作用就是打开浏览器。

真正的难点在于第三部分参数,它的作用是详细规定一个动作要如何完成。很多情况下,学习命令行工具就是在学参数。一个命令可以有几十个参数,它们看似复杂,实际也有规律可循。

参数部分由特殊符号开头。本节一开始列出的四个命令,它们的参数前面是 -(减号)、--(两个减号)或 /(斜杠)这三种特殊符号,后面则是相对贴近自然语言的字母或者单词:virtualdesktop /w /right 的作用切换到右侧的桌面,参数 right 指向右,参数 wWrap 的缩写,表示当切换到最右侧的桌面时,绕回第一个桌面。

在下面这行命令中:

powershell.exe -nologo -file D:\tools\init.ps1 

我们还能发现两类不同参数:-file D:\tools\init.ps1 是常规参数,其结构是 参数名 参数值,也就是说D:\tools\init.ps1file 的具体值。对于常规参数而言,一旦我们写了参数名,往往需要为它指定一个合适的数值:

1

参数名和参数值的连接方式因应用而异。大多数命令用的是空格,不过也有用 = 或者 : 的案例。譬如用 choco 锁定应用(不进行更新)的命令:

choco pin add -name=<应用名>

这里用的就是 = 号。

常规参数之外,-nologo 被称为开关参数(switch parameter)。这类参数只有是和否两种状态。如果我们不写 -nologo,那么 PowerShell 就会显示版权信息,反之则会隐去相关信息。choco 命令中的 re 也是类似的道理。

1

参数的大小写和命令名不同,是由应用开发者控制的。-f-F 极有可能是两个不同的参数,因而在输入参数的时候务必小心。

了解完命令的三大主要成分,在键入命令时你应该会更有信心了。但理解了命令行的语法并不足以帮助我们掌握陌生的命令,我们还需要明确地知道一个命令可以加哪些动作,有哪些参数。

阅读命令行工具的文档

如果诸位有过自行清洗大型家电以及保养汽车的需求,那么家电的说明书和汽车的保养手册一定是参考资料之一。想要知道一个命令的动作、参数,最优解也是阅读命令行工具自带的说明书,计算机领域我们更愿意称之为文档。

命令行工具的自带文档

那么调出命令行工具的文档呢?联系上一节的内容,「帮助」一词作为关键字可能出现在动作或者参数部分中:

command help # 命令名 + 动作(help)
command /? # 以 / 开头的参数
command /h # 以 / 开头的参数
command -h # 以 - 开头的参数
command --help # 以 -- 开头的参数

以上五个命令逐个试下来,能调出绝大多数命令的文档。比如说,chocoscoop 的文档用的是命令名 + help 的形式查阅;cmd 的帮助文档可以用 cmd /? 调出;第二篇文章末尾提到的 VScode 命令的帮助文档是用 code -h

1

一些命令,比如说 yt-dlp,运行失败后会直接告诉你如何调出帮助文档:

yt-dlp --help
1

这些文档就像一本字典一样,详细地告诉你命令的每一个用法以及每一个参数的含义。从头看到尾并不推荐。很多人都会用 Photoshop,但为了简单修图而去学习 Photoshop 的所有选项并不明智。我们需要有目的地看文档,着重把握三个要点:

  • 需要的参数

请大家使用包管理器下载 Node.js,它包含了一个简单的命令行工具 npm,可以安装第三方的 JavaScript 包。下面我们以这个场景为例,利用自带的文档找到全局安装 fanyi 包的命令,这是一个用于终端下的中英翻译工具。

首先自然是查阅 npm 的文档,逐一尝试本节开头列出的五个命令,发现 npm help 就能调出文档:

1

我们需要的是安装(install)一个工具,恰巧对应了文档中对 npm install 的解释。不过这行说明过于简短,再往下看,能发现 npm <command> -h 命令,功能是展示某个命令的帮助文档。所以我们需要再执行 npm install -h。顺便一提,要是你觉得用鼠标滚动太麻烦,在 PowerShell 中可以尝试 Ctrl + L 快捷键,它会将当前输入行置顶:

1

这次展示的文档就更加详细了,它明确告诉我们用 npm 安装一个工具的具体语法是:

npm install [<package-spec> ...]

这行表述用到了两对特殊的符号,[]<>,在命令行工具的文档中,它们有固定的意义,[] 代表可选成分,<> 代表必选成分。也就是说,npm install 后面不加任何东西也能执行成功,但如果要添加什么,必须填上 package-spec,也就是包名。

因为目的是全局安装,就直接在文档中寻找意义近似于全局的参数。Windows 终端也有查找功能,我们可以用 Ctrl + Shift + F 调出:

1

果不其然让我们找到了 [-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 调出其文档:

1

说实话,它的文档写得并不好,具体语法部分和其他部分有冲突,此时示例就非常有用了。列出的三个例子都是用 fanyi 命令名直接加需要处理的词句,文档中又列出了 -S (大写的 S)参数,其功能不发音。之前提到过有的命令参数区分大小写在这个命令也有体现,小写的 -s 参数意味着发音。用它来翻译「kepa」这个单词的命令是:

fanyi kepa -S
1

在网络中搜索文档

当然,除了阅读应用自带的文档,网络永远是我们的好帮手。对于一些命令而言,网络也是获取它们详细用法的唯一渠道。

想要得到命令的具体用法,最好的去处一定是应用的发布处,例如开发者的网站或者 GitHub。比如说我想知道 Word 支持哪些参数。因为 Word 并非为在命令行中使用而设计,所以我们是不能用 winword help 之类的命令调出其文档的,此时,就要在搜索引擎中检索关键词:「microsoft word cli parameter」,输入关键词会比「how to use word in terminal」之类的句子更高效:

1

上图的三个结果中,排名第一的是 Word 的开发商微软的网站,所以那里大概率就有最权威的答案:

1

网友发布的帖子同样有参考价值。命令自带的文档也好,官网给的详细说明也好,都是教科书一般的存在,尽管事无巨细,但少了些针对性。例如,第二篇中提到的图片处理工具 magick,它的文档和官网给的说明多达数十页。假如我只想用它来将图片转换为 jpg,并且保留原来的文件名,倒不如「抄网友的作业」,检索「magick convert to jpeg same name」:

1

排名第一的是知名的 IT 技术类问答社区 stack overflow,简单浏览就能得到想要的答案:

1

不过「抄作业」也要建立在对命令基本的了解之上。网页中给的命令是 mogrify -format png *.psd,其作用是将 psd 转换为 png,如果你尝试直接运行,shell 会报错,你必须事先知道 magick 的基本语法是 magick tools ……,所以我们需要的的命令应该是:

magick mogrify -format jpeg <path>



1

这同时是本文写作的目的,理解了命令行的基本规范,简单翻阅了命令的文档,复制粘贴才会有意义。

前面介绍了两种查阅命令行说明书的方法:调用自带的文档和网络搜索,一开始阅读这些文档可能有些吃力,但随着积累越来越多,我们能够从中找到一些共性,举一反三。这时候,仅需稍加提示,我们就能直接猜出命令,而最好的提示就是命令的具体使用示例。因此,真的有人做了这样一个网站,收录了大量的命令行工具的具体示例,域名也非常好记:shell 的小抄:https://cheat.sh/

1

网站首页写着使用方法:执行 curl cheat.sh/<command> 或者缩写版 curl cht.sh/<command>。cURL(choco install curl -y)是用于发送和处理网络请求的命令行工具,安装此工具后,假如我想知道浏览器 chromium 命令的具体用法,只需执行 curl.exe cht.sh/chromium(PowerShell 5 请不要省略 curl 后的 .exe):

1

数行文档,基本涵盖了各种常见的使用情况,虽然不能替代官方的说明书,但它提供的「太长不读」版本着实能省下不少时间。

三类不同的命令风格

而在我们接触了这么多命令行工具之后,不难发现,在 命令名 动作 参数 这个组合中,外部命令的前两部分都大同小异,但参数部分则各有特点。根据这些特点,我们可以将外部命令分为三类。了解完这三种「模具」,你便能更快地掌握新的外部命令。

Unix sh 风格

计算机发展过程中,在 Unix 时代几个最为流行的 shell —— sh(bin/sh)、Bash(/bin/bash)影响下,命令行的最初规范逐步确立,之所以 Linux、macOS 等 Unix-like 系统上的各类 shell 命令基本一致,便是因为它们或多或少都遵循着这些习惯。

现代的开发者们在设计自己的应用时,常常倾向于和类 Unix 系统上的 shell 命令风格保持一致。因而,Unix sh 风格的外部命令非常常见。比如说我们刚刚用到的 cURL,通过文档观察其语法和参数:

1

命令的特点是:

  • 参数大多由 - 或者 -- 开头;
  • - 后接短参数,即一个字母,-- 后接长参数,即完整的单词,多个单词由 - 连接。前者往往是后者的简写形式;
  • 参数名和参数值之间往往由空格或者 = 连接;
  • 参数区分大小写;

以上四点是所有 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 -fsSLgit -am,这并没有和 Unix sh 风格冲突, 而是同时指定多个短参数的简单写法:curl -fsSL 等同于 curl -f -s -S -L

Windows cmd 风格

从各种意义上,Windows 都不遵循许多类 Unix 系统奉为圭臬的种种习惯。cmd 是微软从 MS-DOS 基础上拓展而来的 shell,这也造就了 Unix sh 风格之外的 Windows cmd 风格,它的典型例子就是 cmd 本身了:

1

其特征是:

  • 参数开头是 / 符号,其后既可以是字母,也可以是单词;
  • 参数名不区分大小写;
  • 参数名和参数值之间由空格或者 : 连接。

调出它们的文档的方法是 command /?。除了 cmd,之前我们用过的 Word、VirtualDesktop 都属于此类。实际上,大部分 Windows 预置的外部命令,以及专门为 Windows 写的应用一般都遵循这类风格,例如 Windows 自带的电源管理小工具,powercfg.exe:用它来生成一份电池使用报告的命令是:powercfg.exe /BATTERYREPORT,将参数小写也是没问题的:

1

相较于一板一眼的 Unix sh 风格,这类的命令设计得非常宽松,一些命令支持省略参数前的 / 符号,或者用 - 代替,这也是为什么大家能在网络上看到同一个命令的各种写法。我仍然建议大家统一地使用 /,因为并非所有应用都支持此特性。

PowerShell 风格

第三种风格的命令更好理解,其特点是:

  • 参数由 - 开头,- 后可以是单词或字母;
  • 参数不区分大小写;
  • 参数名和参数值之间一般用空格分隔。

查阅这类命令文档的方法一般是 command -help,可以缩写为 -h,少数跨平台的应用倾向于使用这种风格,前文展示过的 PowerShell、magick 都属于此类:

1

这是最简单的一类命令,我们只要记住它的参数是由 - 引导的即可。但它们的缺点是命令写起来往往很长。

命令行工具的设置和配置文件

随着学习的深入,我们接触到的命令行工具越来越多,大家可能会有这样的感触:「一些命令打起来很麻烦,如果能简化一下就好了」。确实如此,就以前面用过的两行命令为例:

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

在使用这些命令前大家可以仔细阅读文档,看一看有没有相应的设置:

1

更多情况下,命令的设置藏得比较隐蔽,我们能在其官网找到相关的说明,以 yt-dlp 为例,官网提到,可以在 %APPDATA%/yt-dlp 目录下新建一个 config 文件,将常用的配置写入其中:

1

假如我们想让 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

1

我们习惯于称这类文件为配置文件,因为它们往往以点号开头,英文资料中多用 dotfile 来指代。这和 GUI 应用的设置界面是同样的道理,只不过一个是有图形化界面,另一个只是纯文本而已。GUI 的设置入口多种多样,命令行工具的配置文件的路径也多种多样,Windows 环境下,开发者一般会选择将其设计在如下三个目录下:

  • 用户目录:即 C:\User\<UserName>\,可能默认被隐藏;
  • AppData 目录:~\AppData\Roaming\ 或者 ~\AppData\Local 下的应用开发者亦或应用名文件夹;
  • C:\ProgramData 目录:此文件夹为隐藏状态。

本文是有关外部命令的最后一篇文章,解答了前两篇文章留下的诸多问题:

  • 命令行有统一交互逻辑:语法,也就是 命令名 动作 参数1 参数2 ...
  • 想要了解一个命令的详细用法,可以使用自带的 help 命令调出帮助文档,也可以查阅网络资料。熟练之后,curl cht.sh/<command> 可以帮你省下不少时间;
  • 有三类不同风格的命令,以 --- 引导参数的 Unix sh 风格,参数以 / 开头的 cmd 风格,以及最为简单的 PowerShell 风格;
  • 像 GUI 一样,我们能用配置文件的方式固化命令行工具的设置。

学习完这一篇文章,绝大多数外部命令都难不倒你了,同时如果你回过头去看第一篇和第二篇文章中的那些例子,也应该会有更深的理解。

下一篇文章会从操作文件这个场景切入,讲述 shell 命令。它的使用场景自然也不只是和系统交互,和外部命令不同,shell 命令有着「胶水」一般的效果,我们将不再局限于一行一行死板地执行命令,完成更加复杂的任务。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK