我有非常基本的 Linux 技能,现在正在尝试解析一些 shell 脚本。我在其中一个脚本中看到这一行:
if [ -n "$(which voltdb 2> /dev/null)" ];
我知道 /dev/null 是位存储桶,如果我在命令行运行 voltdb,它会打印出将执行的路径。而且,整行显然是一个 if 语句。但我对这里的许多其他事情感到困惑。
- 为什么将 2 与 /dev/null 进行比较?这些看起来像是不兼容的类型。
- 开关 -n 有何作用?我习惯使用 rm -r filename 等开关,但 -n 似乎不与任何命令配对
- 括号有什么作用?他们在这里似乎有别的意思,而不是在这个表达中这个测试表达式[]是什么意思?
基本上,这条线有什么作用?对我来说,这里面有太多的未知数——所以这有点像听到一个外语句子,错过了很多单词,以至于你无法理解基本结构。
答案1
该代码片段中发生了很多事情。从内到外工作:
which voltdb 2> /dev/null
- 这里执行的命令是which
。which
调用时,将查找环境变量中的所有条目PATH
以查找名为“voltdb”的命令。如果它在 中指定的目录之一中找到名为“voltdb”的可执行文件,它将打印该可执行文件PATH
的完全限定名称。voltdb
为了回答你的第一个问题,“2>”是重定向的一个例子。每个 Unix/Linux/*BSD 进程都有 3 个标准输入和输出,0 是 stdin,1 是 stdout,2 是 stderr。在命令行上运行的程序通常会将错误消息打印到 stderr。因此,“2> /dev/null”并不是在数字上比较 2 和“/dev/null”,而是将任何which
错误输出发送到/dev/null
,一个特殊文件,只接受任何输入,并返回 0 字节的输出。
除此之外,该$(...)
构造意味着“运行所包含的命令并按词法替换此处‘$(’和‘)’之间的任何输出”。这就是输出替换,shell 程序所做的事情。
在输出替换之外,片段会执行if [ -n "something" ];
,其中“某物”是which
要打印的内容。 “if”是 shell 控制流结构,当“if”之后的命令管道以“成功”状态退出时,会导致执行代码块。
实际上是[
一个可执行文件,它查看命令行参数直到]
. “-n”标志通常意味着“对于非零字符串长度的下一个参数为 true”。这就是你的第二个问题和第三个问题的答案。该[ ... ]
构造对某些逻辑条件给出 true(以成功代码退出)或 false(以失败代码退出)答案,在本例中为“非零字符串长度”。
voltdb
最终,当该 shell 的 PATH中有一个包含可执行文件的目录时,该片段将执行 if-then-fi 或 if-then-else-fi 控制流的“true”子句。
答案2
该代码正在执行以下操作:
if [ -n "...." ];
如果双引号中的代码执行结果为空,则 if 语句为 true。
双引号内的代码:
$(which voltdb 2> /dev/null)
运行该which voltdb
命令并将 STDERR(标准错误)上发生的该命令的任何输出重定向到/dev/null
.基本上我们对此不感兴趣,所以我们忽略它。
结果which voltdb
将返回 PATH 上与字符串 voltdb 匹配的任何可执行文件的路径。
例子
$ which time
/usr/bin/time
$ which time 2> /dev/null
/usr/bin/time
关于2>
?
2>
是一种速记符号,用于重定向其中之一的输出溪流这是程序运行时自动设置的。流如下:
- 0 - 标准输入(又名 STDIN)
- 1 - 标准输出(又名 STDOUT)
- 2 - 标准错误(又名 STDERR)
因此,如果您想获取 STDERR 的输出并将其删除:
$ which time 2> /dev/null
如果您想从 STDOUT 获取输出并将其重定向到 STDERR: