在终端上,命令行包括参数(arguments)、命令(command)、选项(option),它们到底指什么,似乎并不重要,糊里糊涂的照样敲命令,但这次不一样,想点搞事情,不得不去查阅一番,结果如下
对于终端(shell、CMD等),命令行如此划分。终端并不关心这些参数的用途,它们由命令负责解释。终端指负责找到命令,并把参数交给该命令执行。
对于命令,划分如上图。其中,选项一定得命令本身支持,否则不能称作选项,即便有相似的格式,例如
# 查询Downloads目录中的文件
# 选项-a:显示以点开头的文件
> ls -a Downloads/
. .. OneKeyMan SpaceMono.zip go1.12.13.linux-amd64.tar.gz
# 将-a替换为-e
# 结果提示e是无效的选项
> ls -e Downloads/
ls: invalid option -- 'e'
Try 'ls --help' for more information.
所以,对于命令 ls ,a是选项,e不是选项。想必大家都注意到了,选项都以 - 开头,这是命令实现的手段,目的是将选项和参数区分开。
到目前为止,一切看着都很清晰,我们可以更进一步。
命令
有功能的可执行程序,可以通过参数调节执行细节。
参数
又叫变量,可以理解为,参与命令运行,调整运行方式的变量。
选项
选项,尽管叫做选项,但仍然有命令强制要求选项的情况,让人困惑。
选项在DOS下叫做开关(switch),这似乎可以避免,必选选项产生的语义矛盾。
现在的Windows CMD和PowerShell中,都叫做选项,和Unix、Linux一致。
短选项,以 - 起头,特点是支持选项组合,例如
# 这三个命令行的执行结果一样
# -l:按照长列表格式显示
# -a:显示以点开头的文件
ls -l -a
ls -la
ls -al
长选项,以 -- 起头,特点是命名不缩写,不支持组合,例如
# 等价于ls -a
ls --all
短选项,看起来很方便,能少敲键盘,组合功能也很棒,果真如此吗?我们看看短选项的缺点吧
-
命名辨识度低,易造成混淆。
# -h: 打印命令帮助信息 awk -h # -h: --human-readable 打印友好的容量大小 ls -h
相比来说,长选项 --help 总是会打印帮助
-
组合是有限制的,要了解清楚,必须通读所有选项的帮助说明
实际上,组合选项会有3种结果
- 命令成功执行,谢天谢地
- 组合了互斥选项,直接报错
- 没有设定先决选项,得不到期望效果
其中,第2点尤其让人头疼,如果有防呆设计就好了
带参数的选项
究竟是什么情况需要带参选项,我们不妨先看个例子
# --max-depth=1:指定命令变量深度为1层
du -h --max-depth=1 .
如果没有这样的设计,势必需要设计 --max-depth1、--max-depth2、--max-depth3 ... 这样可怕的选项,而且难以穷举出所有使用时需求,看来带参数的选项,适用于合并数量多的同类选项。
子命令
这样又是什么需求下的产物,我们再看个例子
比如,windows下的cmd,输入help查看帮助,结果得到许多的命令
C:\Users\noname>help
有关某个命令的详细信息,请键入 HELP 命令名
ASSOC 显示或修改文件扩展名关联。
ATTRIB 显示或更改文件属性。
BREAK 设置或清除扩展式 CTRL+C 检查。
BCDEDIT 设置启动数据库中的属性以控制启动加载。
CACLS 显示或修改文件的访问控制列表(ACL)。
CALL 从另一个批处理程序调用这一个。
CD 显示当前目录的名称或将其更改。
CHCP 显示或设置活动代码页数。
CHDIR 显示当前目录的名称或将其更改。
CHKDSK 检查磁盘并显示状态报告。
CHKNTFS 显示或修改启动时间磁盘检查。
CLS 清除屏幕。
CMD 打开另一个 Windows 命令解释程序窗口。
COLOR 设置默认控制台前景和背景颜色。
COMP 比较两个或两套文件的内容。
COMPACT 显示或更改 NTFS 分区上文件的压缩。
CONVERT 将 FAT 卷转换成 NTFS。你不能转换
当前驱动器。
...
那如果,这个命令仅仅是终端上的一个命令呢?是不是可能和其他命令产生重名呢?我想子命令很好的解决了这个问题,事实上,子命令一些列相关命令,由同一个开发团队维护。
git add
而不是 git-add
,不难发现,子命令除了清楚告诉用户,命令所在域是 git
,单独执行git命令,还能从整体上了解git 命令集,所有子命令的功能全貌,这显然是 git-add
无法达到的。
看来(主)命令,是子命令启动入口,是一层命名空间,也是承载子命令的平台。
注:主命令并非是共识的叫法,英文资料中都叫command,这显然容易混淆,我在这里加了主命令这个叫法,用来区分命令和
支持子命令的命令(表达不出
讨论
基于命令行交互,优点是输入方式统一,高效,多命令协同能力强;缺点是,命令选项使用不直观,需要记忆内容多,上手困难。如果,现在许多应用、游戏在用户首次使用时,会展示操作引导,借此让用户快速上手使用,极少数的命令,提供prompt设计,这些都可以有效降低学习门槛,让命令程序发挥更大价值。
zsh、fish shell提供了prompt,很好的解决了命令多,上手困难的问题,但改变整个shell环境意味着更多的学习成本,事实上大多数人都是从bash入门的。用或是不用,似乎都还不是最想要的选择,我想很多人应该想要折衷的方案。
kube-prompt 是交互友好的kubernetes客户端,从中可以看出,命令自带提示带来的好处
- 可用选项会用自动补全提示,同时你将看到每个选项的帮助说明。
- 通过对提示的编排,有效的避免了使用短选项组合缺点,选项的依赖性、互斥性被隐藏,提示菜单的帮助下,用户总是能做出命令支持的选择。
- 命令自带提示,无需改变整个shell环境,我们照常使用自己熟悉的shell环境,在没有额外学习成本的情况下,更高效,更不易出错。
当然,让每个命令都去实现prompt自动补全,不现实,换一个思路,可以实现一套通用prompt,让每个命令行程序可以简单接入进来,是不是更好呢。
值得一提的是,Windows下目前存在多个shell环境,cmd、powershell、wsl shell,不同的shell差异很大,这无疑给新手用户增加不少学习成本。如果,存在这样一个命令提示补全的包装程序,将cmd、powershell、wsl shell中你最常使用的命令集成进去,包装成带提示自动补全的子命令,是不是很有用呢。
参考内容:
Difference between terms: “option”, “argument”, and “parameter”?