我正在运行这两个命令:
echo $(find ./ $OPT1 $OPT2 $OPT3)
echo find ./ $OPT1 $OPT2 $OPT3 | bash
奇怪的是,顶部命令没有产生结果,而底部命令却产生结果。这是为什么?
答案1
第一个运行find ./ $OPT1 $OPT2 $OPT3
分词并全局输出( 周围没有引号$()
),并将其传递给echo
,后者打印它。这与运行命令基本相同find
,但换行符会变成空格,并且如果包含find
或*
打印任何文件名?
,它们将被扩展。但如果你的内容IFS
包含一些不寻常的东西,分词也会同样不寻常。 (另外,$OPT1
其他的也没有被引用,所以它们在传递给之前被分割和通配find
。)
第二个打印find ./ $OPT1 $OPT2 $OPT3
,扩展变量(再次拆分和通配,因为没有引号),并将结果传递给bash
,后者将其作为命令运行。再次与运行 几乎相同find
,但如果变量包含 shell 元字符,它们将被第二个 shell (再次)扩展。
第一个,请注意文件名foo*
已扩展,通配所有三个:
$ touch foo1 foo2 foo\*
$ echo $(find .)
. ./foo2 ./foo* ./foo1 ./foo2 ./foo1
第二,请注意 bash 的管道会导致内部变量扩展,就像您使用的那样eval
:
$ OPT='echo $BASH_VERSION'
$ echo $OPT
echo $BASH_VERSION
$ echo $OPT | bash
4.3.30(1)-release
$ eval $OPT # about the same
4.3.30(1)-release
变量扩展可能是最简单的示例,但它需要一个导出的变量或其他 shell 在任何情况下都具有的变量,如下BASH_VERSION
所示。 (我find
现在无法想出一个合理的例子。)
根据变量包含的内容,额外的评估轮可能会在是否匹配任何内容OPT
方面产生影响。find