在Shell中,当我们将一个命令放在美元符号和括号内$(command)时,它的含义是执行该命令并返回其输出作为命令行的一部分。

160

我只想理解shell中的以下代码行,它用于获取当前工作目录。 我知道$(variable)会返回变量名内的值,但是$(command)应该返回什么? 它会在执行命令后返回值吗?如果是这样,我们可以使用`来执行该命令。

CWD="$(cd "$(dirname $0)"; pwd)"

在不同版本的Shell中,以下代码行也可以生成相同的输出。

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

我不理解$(cd..$(dirname的含义。

有人能帮我弄清楚这个命令是如何执行的吗?


4
这里有一个关于 $()\`` 的优缺点的问题:https://dev59.com/b2ox5IYBdhLWcg3wFAY1 - None
2个回答

155

$的用法,如${HOME}会给出HOME的值。像$(echo foo)这样使用$表示在子shell中运行括号内的任何内容,并将其作为值返回。在我的示例中,您将获得foo,因为echo将将foo写入标准输出。


40
是的;$(...) 是比使用反引号更好的编写命令的方法。考虑使用gcclib=$(dirname $(dirname $(which gcc)))/lib 的方式来编写。与使用反引号相比,即使在不涉及Markdown的情况下,它也更难,因为您必须转义嵌套命令的反引号,而使用 $(...) 符号则无需这样做。 - Jonathan Leffler
8
从技术上讲,$(echo foo) 创建了一个命令替换(command substitution),而不是一个子 shell。另一个当前的答案说得对。我认为命令替换在某种程度上是在子 shell 中运行的,但它们仍然是不同的概念。 - trysis
9
@trysis - 命令替换[绝对]在子Shell中运行,因此值得注意。 - Eliran Malka
2
我知道反引号(backticks)和$()产生的结果相同,但是它们之间的区别纯粹是表面上的吗?除了$()更易读之外,是否有使用其中一个而不是另一个的原因? - Mitchell Tracy
4
使用$符号,如$(echo foo),表示在子shell中运行括号内的命令并将其作为值返回。这很容易引起困惑,因为命令$(echo foo)会尝试运行括号内返回的内容,它会首先运行echo foo,然后尝试运行foo,从而导致错误。 - Accountant م

26
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

Could anybody help me to figure out how this command get executed?

让我们来看一下命令的不同部分。 BASH_SOURCE 是一个包含源文件名的 bash 数组变量。因此,"${BASH_SOURCE[0]}" 将返回脚本文件的名称。 dirname 是 GNU coreutils 提供的一个实用程序,它删除文件名的 最后一个组成部分。因此,如果您通过 bash foo 来执行脚本,则 "$( dirname "${BASH_SOURCE[0]}" )" 将返回 .。如果您说 bash ../foo,它将返回 ..;对于 bash /some/path/foo,它将返回 /some/path
最后,整个命令 "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 获取包含被调用脚本的绝对目录。 $(...) 允许命令替换,即允许命令的输出替换命令本身,并且可以嵌套使用。

1
很抱歉我来晚了三年,但你能否解释一下这个语句为什么有效呢?你说dirname返回执行文件的路径(相对于当前工作目录或绝对路径),cd将pwd更改为该目录,并且pwd打印出当前工作目录的绝对路径。但是它们为什么要用&&连接起来呢?如果cd失败,DIR会保存什么内容? - Christian
3
@Christian,“&&” 的作用是防止在“cd”失败时运行“pwd”,这样“DIR”将为空,而不会包含错误的目录。 - Charles Duffy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接