在命令行参数中使用短划线“-”
1. 概述
在本教程中,我们将了解“-”字符的含义以及它的用途。我们将看看使用“-”比其他方法更有意义的最常见用例。
2. “-”字的含义
**“-”字符对 Linux 终端上的不同命令有不同的含义。在 Linux 命令中使用“-”字符没有通用约定。**但是,在bash 和zsh 等最常用的 shell 上,“-”字符用于指定命令的标准输入或标准输出。这是许多 Linux 实用程序的特定于命令的约定。
**另一方面,Linux 上的其他工具或命令可能对“-”字符有不同的用例。**例如,我们在git 命令中使用“-”来指定存储库分支。对于期望文件作为输入的其他工具,例如tar ,“-”字符用于将另一个命令的输出视为输入文件的内容。因此,我们不需要指定命令的文件路径。
3. 使用“-”指定标准输入
Linux 上的大多数命令将字符串“-”视为stdin或stdout 的同义词。因此,例如,当我们使用带有裸“-”的cat命令时,它将从stdin 读取:
$ cat -
I am being echoed.
I am being echoed.
上述命令中的“-”实际上是*/dev/stdin的别名。因此,我们也可以将“-”替换为/dev/stdin*,不会有任何变化:
$ cat /dev/stdin
Echo this.
Echo this.
所以,这就引出了一个问题,什么是*/dev/stdin*?好吧, /dev/stdin是/proc/self/fd/0*的符号链接。/ proc/self/fd/0又是一个符号链接,指向我们当前 shell 进程的标准输入,也就是我们的终端*。因此,我们可以使用终端向cat命令输入文本。
同样,我们可以使用tar命令提取 tarball 并将其打印到stdout。打印到stdin的 tarball 的内容将作为 tar命令的输入,该命令将解压缩内容并将它们写入磁盘,如下面的片段所示:
$ <htop-2.2.0.tar.gz | tar -xzf -
让我们分解一下:
- 我们使用重定向运算符*<将htop-2.2.0.tar.gz存档的内容打印到stdout*
- 然后我们将命令传递给tar,它从stdout读取htop-2.2.0.tar.gz的内容
- -x选项提取文件,或者在这种情况下提取stdout的内容
- -z选项通过gzip 过滤内容
- -f选项将提取的内容写入文件或目录
使用带有“-”的tar的另一个实际用例是当我们想要下载远程文件并在下载后将其解压缩。我们可以使用curl 将下载文件的文本或二进制输出打印到stdout。然后,我们可以将打印到stdout的任何内容通过管道传输到tar并将stdout的内容指定为stdin:
$ curl -L https://github.com/hishamhm/htop/archive/refs/tags/2.2.0.tar.gz --output - | tar zxf -
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 130 100 130 0 0 135 0 --:--:-- --:--:-- --:--:-- 135
100 168k 0 168k 0 0 77436 0 --:--:-- 0:00:02 --:--:-- 309k
$ ls -lF
drwxr-xr-x hey hey 4.0 KB Wed Dec 1 22:41:43 2021 htop-2.2.0/
4. 使用“-”指定标准输出
同样,我们也可以使用“-”来指定特定命令的标准输出。在我们的curl示例中,我们使用“-”将远程文件的二进制输出打印到我们的标准输出:
$ curl -L https://github.com/hishamhm/htop/archive/refs/tags/2.2.0.tar.gz --output -
E�P��7�&�3Dq�"!GKvL�[f>��GY6as<Hl�'�)2'AS�*��~맊VT#a;�}x܍ҋ�zN
�8YWslw>���bmLf-~r+�����ju��WTr
��υ<��u�kIM�wyfٚ9~a9
...
正如我们所见,我们明确告诉curl命令输出二进制文件的内容,因为默认情况下curl不会将二进制内容打印到stdout。与stdin一样,当在stdout的上下文中使用“-”时,它是/dev/stdout*的别名。*
因此,有人可能想知道为什么我们将二进制输出打印到标准输出。好吧,我们可以用它做很多有用的任务。在我们的下一个示例中,我们将编写一个命令,该命令基本上使用curl下载图片,然后使用 ImageMagick 从图像中创建一个网站图标。调整图像大小后,我们会将其转换为 base64 并将结果 POST 到端点。我们将只通过读取和写入stdin和stdout来完成所有这些任务,而无需将内容保存在磁盘上的文件中:
$ curl https://upload.wikimedia.org/wikipedia/commons/4/45/Linux-for-workgroups-boot.jpg --output - \
| convert - -resize 16x16 png:- \
| base64\
| curl -X POST --data @- -H 'Content-Type: text/plain' https://example.com/favicon
让我们分解一下:
- 在我们的第一个命令中,我们下载一张图片并使用*–output –选项将其二进制内容打印到stdout*
- 接下来,我们将内容通过管道传递给convert 命令,该命令从stdout读取并调整图像大小
- 调整图像大小时,调整大小图像的 PNG 内容将打印到stdout,如png 所示:-
- 之后,内容通过管道传递给base64 命令,该命令打印出调整大小的 favicon 的 base64 内容
- 最后,curl使用从标准输出中挑选的数据向我们的示例端点发出一个 post 请求,如*–data @-*选项所表示
正如我们所见,我们对stdin和stdout都使用了“-” 。由命令本身来相应地解释它。当然,我们可以把“-”换成/dev/stdin和/dev/stdout,结果是一样的。**
5. Git 分支使用“-”
众所周知,“-”对不同的命令有不同的含义。**对于git,我们可以使用它作为git checkout命令的参数来检查之前的活动分支或分离的 HEAD。**例如,如果我们有一个 Git 存储库和存储库上的两个分支,我们可以使用“-”在这两个分支之间切换:
$ git branch -a
*master
dev
$ git checkout dev
$ git branch -a
master
*dev
$ git checkout -
$ git branch -a
*master
dev
6. 在cd命令中使用“-”
同样,与git命令一样,我们也可以使用“-”作为cd 命令的参数来在当前目录和上一个目录之间切换。
让我们看看它的实际效果:
$ pwd
/home/hey/github
$ cd TestApp
$ pwd
/home/hey/github/TestApp
$ cd -
$ pwd
/home/hey/github
$ cd -
$ pwd
/home/hey/github/TestApp
我们的 shell 将旧路径存储在称为$OLDPWD 的环境变量中。因此,“-”参数充当*$OLDPWD*的别名:
$ echo $OLDPWD
/home/hey/github/TestApp
$ cd $OLDPWD
$ pwd
/home/hey/github/TestApp
$ echo $OLDPWD
/home/hey/github
7. 我们还能在哪里使用“-”?
正如我们所看到的,由每个工具或命令来解释“-”参数。但是,许多其他工具出于不同目的使用“-”参数。确定工具是否支持“-”参数的最常见和最可靠的方法是查看其官方手册页。