我最近遇到了一些设置环境变量并在同一命令中启动子进程的示例:
$ TEST="test" sh -c 'echo $TEST"
以前,我一直使用env:
$ env TEST="test" sh -c 'echo $TEST"
有人能指出我对第一个例子的解释吗? 使用env有什么好处吗?
答案 0 :(得分:3)
env
的一个重要用途是使用find
命令。
这将不工作:
find . -exec f={} somecommand \; # Won't work
这将有效:
find . -exec env f={} somecommand \;
原因是find
希望-exec
之后的第一个参数成为可执行文件,env
满足该要求。
显示使用env
与find
一起使用的便利性的相关示例是来自Dennis Williamson的此函数:
targz() {
find "$1" -type f -name "*.$2" -exec \
env ext="$2" bash -c 'old=$(basename "{}"); new=${old/%$ext/tar\.gz}; \
tar -zcvf "$new" "$old"; ' \;
}
答案 1 :(得分:3)
使用env
的原因很少。大多数情况下,您可以(并且应该)使用更简单的语法:
var=value ... command
这是Posix标准,应该可以在任何与Posix兼容的shell中使用(包括/bin/sh
)。
以下是env
有用的几种情况:
上述语法在csh
(或派生词)中不起作用,也不适用于fish
。因此,在这些非Posix shell中,本地环境修改需要env
。
-i
的{{1}}参数使用仅包含 指定环境变量的环境启动指示的命令。这可用于运行不受信任的命令,而不会通过环境变量泄漏信息。 (但要小心:必须设置一些环境变量才能正常运行,从env
开始。)
PATH
使用env
环境变量将命令的名称解析为可执行文件,可能在PATH
命令行中进行了修改。在未执行路径名解析的上下文中(例如,shebang行),使用env
(使用正确的完整文件路径)可以节省必须知道所有其他可能的可执行文件的精确路径。 (正是由于这个原因,它在shebang线中经常遇到)。
在调用env之前,shell会扩展env
的参数。因此,还可以计算环境变量的名称,这是使用标准shell语法无法实现的:
env
这在从数组扩展环境时(在bash中)特别有用:
env "$name=$value" command ...
(此处,env -i "${new_env[@]}" command ...
应为new_env
形式的数组
(var1=val1 var2=val2 ...)
将打印出(可能已修改的)环境,每行一个环境变量。我没有找到这个有用的功能,但它在Posix基本理由中继续存在env
实用程序:
有些人认为env是多余的,因为通过以下方式实现了相同的效果:
name = value ... utility [argument ...]
该示例等同于将环境变量添加到命令环境时的env,但是当环境设置为给定值时则不等效。如果不带参数调用,env实用程序也会写出当前环境。除了示例提供的功能之外,还有足够的功能来证明包含env。
答案 2 :(得分:1)
env
是一个程序,它使用提供的参数调用(作为分叉子进程)提供的命令,将累积的环境传递给命令。
TEST="test"
是shell支持的功能(例如bash
)。在大多数情况下,它与env TEST="test"
具有相同的效果,但没有env
进程作为中间人运行。
由于几乎所有现代炮弹都支持TEST="test"
,因此使用这种方法通常是安全的。
答案 3 :(得分:0)
我猜想有些旧的或模糊的shell不支持第一种语法(TEST=test sh
)。如果希望脚本在这样的shell中工作,则必须使用单独的实用程序(如env
)为子进程设置环境变量。