CLICommand-Line Interface 的简称,也就是 命令行界面,通俗来讲就是用输入命令的方式与计算机交互。可能大部分人都看到命令行很头疼,感觉这些东西复杂又难记,不过其实还好啦,大部分选项参数设计的都蛮合理的,只要稍微理解它,你也可以成为 CLI 大师。

参数和选项(arguments & options)

一条命令通常由三个部分组成:命令、选项和参数。命令很好理解,比如:whoamicurl 或是 node 等等这些都是命令。在使用命令时可能需要告诉它各种执行细节,这就是选项和参数的作用,它们根据命令不同具有不同的可选性,某些命令可能不需要参数,某些命令可能没有选项(虽然不常见,但这是允许的)。

选项

选项通常用于修改命令的行为或提供额外的信息。选项使用一个或两个短线(-)开头,许多选项需要一个额外的值跟着它们。单短线的短选项格式,可以使用一个空格在选项和值之间隔开或是不隔开,不过更推荐使用空格隔开;如果是双短线的长选项格式,则必须使用一个空格在选项和值之间隔开(有时也用 =,具体使用请查阅使用命令的相关文档)。此外不需要任何额外值的短选项可以彼此紧挨着使用。

参数

一条命令可以有多个参数,用于标识信息的来源或目的地,对位置比较敏感,比如:mv source.txt destination.txt。参数一般是需要操作的内容,可能是一个文件路径、一段文本或是标准输入流。

Tips:在类 Unix 操作系统中,有些命令可以使用一个短线代替文件名,这将会使其处理来自标准输入的数据或将数据发送到标准输出。

使用语法说明

当你第一次接触某个命令,想快速获取它的用法时,通常可以使用 --help-h 此类选项查看一些简短的用法说明。下面这些语法说明会帮助你快速理解选项和参数的可选性:

  • 尖括号(<key>)代表必需参数,例如:ping <destination>
  • 方括号([key])代表可选参数,例如:mkdir [OPTION] <dirname>
  • 省略号(...)代表可重复参数,例如:cp <source1> [source2...] <dest>
  • 竖线(|)代表可选择参数,例如:ip [OPTION] OBJECT { SUBCOMMAND | help }

上述这些符号只是辅助理解如何使用命令的,在终端中实际使用这些命令时不需要再次按照参数的可选性增加这些符号,尖括号所包裹的参数在不容易混淆的情况下可能不会额外标记。

重定向和管道(redirect & pipe)

标准输入输出流(Standard Input/Output Streams,简称标准 I/O 流)是程序与外界交互的基础。标准 I/O 流主要包括标准输入流(stdin)、标准输出流(stdout)和标准错误流(stderr),分别可以用文件描述符 012 来指代。在 Unix 命令行中,我们经常使用重定向和管道来管理这些输入输出流,以便更高效地处理数据和信息。

重定向

重定向的语法非常简单,使用 < 代表重定向输入,使用 > 代表重定向输出。通过重定向输入可以将文件内容作为标准输入流传递给程序,重定向输出则是将程序的标准输出流写入到文件,如果执行一个命令同时需要重定向输入和输出的话,看起来会是这样:command < input > output。重定向输入实际上等价于 0< input,同样的重定向输出实际上等价于 1> output。使用 > 将会将标准输出流重定向到一个文件,如果文件存在则会覆盖原内容,也可以使用 >> 将标准输出流重定向并追加到指定文件。

某些情况下,我们可能需要把标准错误、标准输出一并记录并处理,那这时就需要重定向这些标准流。例如,我需要将标准错误重定向至标准输出,就需要这样:command 2>&1,如果是将标准输出重定向到标准错误,则是这样:command 1>&2

管道

在处理数据时,管道也是非常强大和常用的工具,使用 | 将左边命令的标准输出连接到右边命令的标准输入,可以将多个命令组合在一起。多条指令使用管道依次传递看起来会使这样:command1 | command2 | command3。管道允许实时处理数据流,命令可以即时地处理输入流的部分内容,而不必等到整个输入流完全生成。默认情况下,标准错误将不会被通过管道传递,它们将会合并并直接输出到终端上,你可以使用重定向标准错误到标准输出来改变这一行为。

返回值(exit code)

与常见的 True False 布尔值返回结果不一样,在命令行中成功都应该返回 0,而其他的返回代码都可能代表着错误或失败,通常来说每个命令都会定义自己的错误码,如果你执行的命令出现了错误可以使用 echo $? 获取到错误码,这在写自动化脚本检测失败时会很有用。

结合 &&|| 运算符就可以根据命令的执行结果决定后续的操作,例如在 command1 && command2 命令中,如果 command1 执行成功(exit code 等于 0)则执行 command2;反之在 command1 || command2 中,如果 command1 执行失败(exit code 不等于 0)则执行 command2

配置文件(config)

通常这些命令的全局配置文件都在 /etc 或是 /usr/local/etc 目录中,用户自定义的配置文件通常在 /home/<username>/.<something>rc 此类的文件中。至于 rc 后缀的起源众说纷纭,我们约定成俗,见到 rc 一般当作配置文件都没什么问题。当然,每条命令也可以有自己的配置文件格式,例如:curl 的配置文件通常是按行写各种选项,而 wget 的配置文件则像是一个个的键值对。

环境变量(environment variable)

环境变量是一种在操作系统中用来存储信息的机制,它们包含了系统运行时所需的各种信息,如路径、默认参数、语言设置等。每个环境变量都有一个名称和一个对应的值。通常来说定义环境变量应当全大写,设置环境变量可以采用多种方法,可以根据需要在命令行中临时设置或者在系统中永久生效。

某些命令行程序也会读取项目中会的 .env 或是其他环境变量文件,也会有像是 NODE_ENV=development vite build 此类直接在命令前定义的环境变量的情况,这种情况环境变量不会被记录仅在当前命令中有效。

我们还可以在终端中直接 export 一个环境变量,这样定义的环境变量将仅在当前会话中可用,重启终端或退出登录等操作都会使其失效。比如这样:

export NODE_ENV=development
vite build

如果你想持久化的定义一个环境变量可以将它在 .zshrc 或是 .bashrc 等终端配置文件中 export,在启动该终端时自动添加这些环境变量。例如:

export PATH="/usr/local/go/bin:$PATH"

小测

指出 ls -lah --time=ctime --color auto . 命令中各个成分ls -lah --time=ctime --color auto . 中,-lah 是一组短选项,--time=ctime 是一个长选项并指定了一个值,--color auto 也是一个长选项它指定了一个值并使用空格分割,. 是参数指代当前目录,并且在这个例子中参数和选项都是可以省略的。
重定向标准输出和标准错误到一个文件
  • 正确的做法:myprogram > all_output.txt 2>&1,这个命令表示先将标准输出(文件描述符1)重定向到 all_output.txt,然后将标准错误(文件描述符2)重定向到标准输出(文件描述符1),确保两个流都指向同一个文件。
  • 错误的做法:myprogram 2>&1 > all_output.txt,这个命令的意思是将标准错误(文件描述符2)重定向到标准输出(文件描述符1),然后再将标准输出重定向到all_output.txt。由于标准输出在这时已经被重定向,所以标准错误仍然会输出到终端而不是文件中。
说出 seq 1 5 | tr 1-9 a-z | sort -r 的输出
1
2
3
4
5
a
b
c
d
e
e
d
c
b
a

结语

相信你读完这篇文章对命令行再也没有那么恐惧了,大多数参数与选项设计得都很合理且便于记忆,稍加使用一段时间你将会发现命令实在是太酷了!

参考文档

Photo by Nathan da Silva on Unsplash