放
  • 什么set和命令之间有什么区别env

  • 什么时候是否应该使用其中一个而不是另一个?

  • 如何它们通常会被调用吗?(典型用途;案例场景)。

答案1

setshell 内置命令命令。

(由于该问题被标记为 Unix shell,因此我省略了 MS Windows 命令。)

POSIX 规范

内置set的是POSIX 中定义具有多种功能。

1. 位置参数

内置函数的主要目的set

设置或取消设置选项和位置参数。

位置参数由调用程序(通常是(但不一定)是另一个 shell)作为参数传递给 shell(通常是脚本,但可以是交互式的)。第一个参数为$1,第二个参数为$2,等等。

set命令可以操纵这些参数。每个争论提供给它的设置为位置参数,例如

$ set one two
$ echo "$1"
one
$ echo "$2"
two

set --取消设置所有位置参数:

$ set --
$ echo $1   # no output

2. 列出 shell 变量

然而,POSIX 规范还描述了其他用途set

运行set本身会打印所有 shell 变量的名称和值。这包括

  • 全部shell 变量在当前 shell 中设置并
  • 全部环境变量从其父进程继承。

例子:

$ set

HOME='/home/ant'
IFS='
'
LANG='en_US.UTF-8'
LANGUAGE='en_US:en'
PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
PS1='# '
PS2='> '
PS4='+ '
PWD='/home/ant'

在上面的列表中HOMELANGPATH环境变量whileIFSPS1toPS4都是shell 变量已在当前 shell 中设置。

注意:在 Bash shell 中,set内置命令还会打印 shell 函数的定义。有关更多信息,请参阅 set 的 Bash 手册。

3. 壳的控制行为

set还用于控制 shell 的属性,通常(但不一定)是交互式 shell。这是通过运行某些预定义的选项(为了将它们与上面描述的用于设置位置参数的参数区分开来)。

当指定选项时,它们应设置或取消设置 shell 的属性

这些选项的详细信息POSIX 规范. 一个例子是

set -f

-f选项禁止当前 shell 执行路径名扩展 (globbing)。此行为也可以使用等效命令配置:

set -o noglob

Bash 等 Shell 会扩展此列表以包含诸如-B(或-o braceexpand) 之类的选项;这将启用当前 Shell 中的括号扩展(仅限 Bash 的功能)。


环境

与 不同set,该env命令是常规的外部命令,即它不是 shell 的一部分。按照惯例(为了可移植性),在每个 Unix 环境中,该env程序都是安装到目录中的可执行文件/usr/bin

POSIX 规范

env工具还由 POSIX 指定

1. 修改命令的环境

该命令的主要目的env是运行具有不同/修改的环境的命令。

env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]

以下示例git status使用两个环境变量设置来运行该命令:

env GIT_DIR=~/notes/.git/ GIT_WORK_TREE=~/notes/ git status

-iwith 选项可env用于运行具有空环境的命令,即,没有从父进程继承任何环境变量。

请注意,如果仅修改一两个环境变量并使用 Bash shell ,则无需这样做,env因为 Bash 本身已经可以临时修改一个命令的环境。在 Bash 中,上述示例可以简单地运行如下:

GIT_DIR=~/notes/.git/ GIT_WORK_TREE=~/notes/ git status

2.打印环境变量

如果没有提供命令,则会打印当前环境。

$ env

MAIL=/var/mail/root
LANGUAGE=en_US:en
USER=ant
HOME=/home/ant
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LANG=en_US.UTF-8

请注意,这仅打印环境变量 – 而不是诸如PS1或 之类的shell 变量IFS

3. 搜索 PATH 来运行已安装的程序

的另一个用途env是在 PATH 中搜索命令。

它还可用于运行由 shell 特定命令所遮蔽的外部命令。由于它对 shell 内置命令、关键字、函数或别名(shell 定义的和为 shell 定义的任何东西)一无所知,因此它会在环境变量指定的目录中搜索可执行文件PATH

使用系统命令代替 Bash 内置命令,无需指定完整路径

env在(可能)修改的环境中运行由其第一个参数命名的可执行文件;因此,它不知道或无法使用 shell 内置命令。

例如,此命令将运行 shell 内置版本echo

$ echo --version
--version

另一方面,运行echoenv执行安装在的程序/usr/bin/echo

$ env echo --version
echo (GNU coreutils) 8.15
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

4. 脚本

上述行为通常用于可执行脚本的 shebang(第一行),以确保内核使用正确的程序来解释脚本 - 而无需指定解释器程序安装在哪个目录中。

例如,Python 安装在不同系统的不同位置(没有标准位置)。以下 shebang 将导致程序运行脚本python3- 只要它安装在PATH环境变量中指定的目录之一中。

#!/usr/bin/env python3

可以在交互式 shell 中通过在命令行中输入以下内容来测试此用法:

$ /usr/bin/env python3 --version
Python 3.2.5

这个优秀的答案“/usr/bin/env 如何知道要使用哪个程序?”

内核不想知道诸如这样的环境变量PATH。因此 shebang 行上的名称必须是可执行文件的绝对路径。

该命令的主要目的env是运行具有不同环境的命令,但是因为它在中查找命令名称$PATH,所以它可以用来向内核提供命令的路径

尽管这并未得到官方保证,但历史上的 Unix 系统提供了 env/usr/bin而现代系统正是由于 的广泛使用才保留了该位置#!/usr/bin/env

基本上,使用env更具可移植性,因为这意味着脚本不需要知道启动命令的首选二进制文件安装在哪里。另请参阅为什么使用“#!/usr/bin/env NAME”而不是“#!/path/to/NAME”作为我的 shebang 更好?

相关内容