4.3 修改 Shell 行为(Modifying Shell Behavior)

4.3.1 内建命令 set(The Set Builtin)

这个内建命令相对来说比较复杂,所以要使用一个小节来进行说明。你可以使用“set”来改变 shell 选项的值和设置位置参数,或用来显示 shell 变量的名称和其值。

set [--abefhkmnptuvxBCEHPT] [-o option-name] [argument ...] set [+abefhkmnptuvxBCEHPT] [+o option-name] [argument ...]

如果没有选项或参数出现,set 则显示所有变量和函数的名称和值。其显示顺序是按当前语言区域字母顺序。其显示格式是可用于重新输入对其当前变量进行设置或重置的格式。只读变量不能进行重置。在 POSIX 模式中,只会显示出 shell 变量。

当在命令中使用了选项,可对 shell 属性进行设置或释放。如果指定了选项,则具有下列含义:

-a

每个创建或修改的变量或函数都具有导出属性,并且标记为可导出到后继命令的执行环境中。

-b

会立即报告已终结的后台作业状态,而不是在下一个主提示符出现之前打印。

-e

如果由简单命令、或命令列表、或复合命令组成的管道返回一个非零状态时,则立即退出。如果这些失败的命令出现在:紧随关键字“while”或“until”后面出现的命令列表中的一部分时;在“if”语句中测试条件部分中;在“&&”或“||”列表中的一部分,但这两个操作符不作为终结符时;在管道中的任意命令,但不是最后一条命令;或命令返回状态是使用“!”进行反转的,Shell 都不会退出。如果因为当“-e”被忽略时执行一个命令失败引起了非子 shell 的复合命令返回一个非零状态,则 shell 不会退出。如果设置了 ERR 捕获器,在 shell 即出之前会执行该捕获。
该选项分别应用于 shell 环境和每一个子 shell 环境。并且可能引起在子 shell 执行所有命令之前就退出该子 shell。
如果在忽略“-e”的上下文中执行一个复合命令或 shell 函数,没有一个执行于复合命令或函数主体中的命令会被“-e”的设置所影响,即使设置了“-e”选项并且命令返回一个失败状态。如果在一个忽略“-e”的执行上下文中的一个复合命令或 shell 函数设置了“-e”,则直到复合命令或命令包含的函数调用完成后,这个设置才会生效。

-f

禁用文件名扩展(globbing)。

-h

定位并且记住(使用哈希表)已查找过的可执行命令。该选项默认开启。

-k

所有用于命令的赋值语句形式的参数都放置于环境中,不仅仅是命令名前面那些。

-m

开启作业控制。所有进程运行在一个分开的进程组中。当一个后台作业完成时,shell 打印一行退出状态。

-n

只读取命令但不执行它们。这可以用于检查脚本的语法错误。在 shell 交互模式下忽略这个选项。

-o option-name

依照“option-name”来设置选项:

-p

开启特权模式。在这个模式下,不会处理在“$BASH_ENV”和“$ENV”中的文件;不会从环境中继承 shell 函数;如果在环境中出现变量“SHELLOPTS”、“BASHOPTS”、“CDPATH”和“GLOBIGNORE”时,则忽略它们。如果 shell 启动时的有效用户(或组)id 不等于真实用户(或组)id,并且没有给出“-p”选项,则会进行上面的这些动作并且将有效用户 id 设置为真实用户 id。如果在启动时给出了“-p”选项,则有效用户 id 不会被重置。关闭这个选项会使有效用户 id 和组 id 设置为真实用户 id 和组 id。

-t

在读取并执行一个命令后退出。

-u

在执行参数扩展时,视未设置的变量和参数为错误,但不包括特殊参数“@”和“*”。报错信息会写入标准报错流中,并且非交互模式的 shell 会退出。

-v

打印 shell 输入行读取的内容。

-x

在简单命令、for 命令、case 命令、select 命令和算术 for 命令扩展之后和执行之前,打印其追踪信息和其参数或关联的单词列表。在命令和其扩展参数之前,先打印变量 PS4 值的扩展结果值。

-B

Shell 会执行大括号扩展(参见 3.5.1《大括号扩展》)。该选项默认开启。

-C

防止使用“>”、“>&”和“<>”重定向将现有文件进行覆盖。

-E

如果设置该项,在子 shell 环境中执行的 shell 函数、命令替换和命令可继承任意 ERR 捕获器。通常在上述情况下不会继承 ERR 捕获器。

-H

开启“!”风格的历史替换(参见 9.3《历史交互》)。在交互模式下的 shell 该选项默认是开启的。

-P

如果设置了该项,在执行像“cd”这种改变当前工作目录的命令时,不会对软链接进行解析。则是使用物理目录代替。默认情况下,在使用命令改变当前目录时,Bash 会跟随目录逻辑链。 例如,如果“/usr/sys”是一个指到“/usr/local/sys”的软链接,则:

$ cd /usr/sys; echo $PWD
/usr/sys
$ cd ..; pwd
/usr

如果设置了“-P”选项,则:

$ cd /usr/sys; echo $PWD
/usr/local/sys
$ cd ..; pwd
/usr/local

-T

如果设置该项,在子 shell 环境中执行的 shell 函数、命令替换和命令可继承任意 DEBUG 和 RETURN 捕获器。通常在上述情况下不会继承 DEBUG 和 RETURN 捕获器。

如果在该项后没有跟随“argument”参数,则将所有位置参数释放。否则,将位置参数设置为给出的“argument”参数,即使它们其中的一些开头是“-”。

-

代表选项结束,将所有剩余“argument”参数分配给位置参数。关闭“-x”和“-v”选项。如果没有给出“argument”参数,则不对位置参数进行任何改变。


使用“+”而不是“-”来对选项进行关闭操作。这些选项也可以在调用shell时使用。当前选项的设置可以在变量“$-”中找到。

命令后面的 N 个“argument”参数是位置参数,并按顺序分配给“$1”、“$2”到“$N”。特殊参数“#”设置为 N。

返回状态总是为零,除非提供了一个无效的选项。

4.3.2 内建命令 shopt(The Shopt Builtin)

该内建命令可以让你更改额外的 shell 可选的行为。

shopt [-pqsu] [-o] [optname ...]

使用开关设置切换控制可选的 shell 行为。这些设置可以是下面列出的这些,或如果使用了“-o”选项,则可以设置内建命令 set 的“-o”选项。运行命令时不加选项,或使用“-p”选项时,则列出所有可设置选项,指出这些选项是开启了还是未开启;如果给出了“optname”参数,则只输出这些选项。“-p”选项可以使输出的显示格式可重新用于输入设置。其它选具有以下含义:

选项含义
-s开启(即设置)每个给出的“optname”选项。
-u关闭(即释放)每个给出的“optname”选项。
-q抑制普通输出;返回状态反映的是“optname”选项是设置了还是释放了。如果在使用“-q”时给出了多个“optname”参数,则如果所有“optname”是开启的,返回状态为零;否则为非零。
-o限制“optname”的值只是定义在 set 命令中“-o”选项的值。

如果在使用“-s”或“-u”选项时不加“optname”参数,shopt 只会显示开启的或关闭的 shell 选项列表。

除非有其它注释,shopt 选项默认是关闭的。

如果列出的所有“optname”的选项都是开启的,则返回状态为零;否则为非零。当在设置或释放选项操作时,其正常返回状态为零,除非“optname”是一个无效的 shell 选项。

shopt 选项列表:

assoc_expand_once

如果开启了该选项,在执行可执行变量赋值的内建命令时,和在执行数组引用解除的内建命令时,shell 会在算术表达式运算期间抑制关联数组下标的多次运算。

autocd

如果开启了该选项,可将目录名作为一个命令名执行,就像其作为 cd 命令的参数一样执行。该选项只用于交互式 shell。

cdable_vars

如果开启了该选项,如果内建命令 cd 的参数不是一个目录的话,则假设其是一个变量名,其值作为要改变的目标目录。

cdspell

如果开启了该选项,在 cd 命令中对于目录的微小拼写错误会被更正。会对字符的颠倒顺序、字符缺失和单一字符重复进行错误检查。如果找到纠错,则打印纠正的路径并运行命令。该选项只用于交互式 shell。

checkhash

如果开启了该选项,Bash 会在试图执行命令之前在哈希表中查找该命令。如果哈希表中不存在该命令,则执行常规的命令搜索操作。

checkjobs

如果开启了该选项,在退出交互式 shell 之前,Bash 会列出所有已停止和正在运行的作业状态。如果有作业处于运行状态,这会引起在没有干预命令情况下延迟退出 shell,稍后会再次尝试退出。

checkwinsize

如果开启了该选项,Bash 在执行外部命令(非内建命令)之后会检查窗口大小。并且如果需要,会更新变量“LINES”和“COLUMNS”的值。该选项默认开启。

cmdhist

如果开启了该选项,Bash 会试图将多行命令输入的所有行保存为一个命令历史记录。这使得多行命令更容易重新编辑。该选项默认开启,但仅在开启了命令历史记录才生效。

compat31 compat32 compat40 compat41 compat42 compat43 compat44

这些用于控制 shell 的兼容模式。(参见 6.12《Shell 兼容模式》)

complete_fullquote

如果开启了该项,Bash 会在执行补全时将所有在文件名和目录名中的 shell 元字符引起来。如果关闭了该项,当像美元符号“$”这样的元字符出现在补全的多个单词中作为变量引用时,Bash会从将要引起来的已补全文件名的字符集中移除这样的元字符。也就是说,要扩展为目录的变量名中的美元符号“$”将不会被引起来;不管怎样,所有出现在文件名中的美元符号“$”也不会被引起来。这只有当 Bash 使用反斜线来引用补全的文件名时才被激活。该变量默认开启,其是 Bash 4.2 以后版本的默认行为。

direxpand

如果开启了该选项,当执行文件名补全时,Bash 使用单词扩展的结果来替换目录名。这会改变读入行编辑缓冲的内容。如果未开启该项,Bash 试图保留用户的输入。

dirspell

如果开启了该选项,如果最初提供的目录名不存在,Bash 会试图在单词补全时对目录名进行拼写纠正。

dotglob

如果开启了该选项,Bash 在文件名扩展结果中包含了以点符号“.”开头的文件名。文件名“.”和“..”必须始终被精确匹配,即使开启了“dotglob”选项。

execfail

如果开启了该选项,在一个非交互 shell 使用内建命令 exec 执行一个不能执行的外部命令时,其不会退出。交互式 shell 在使用 exec 执行命令失败后是不会退出的。

expand_aliases

如果开启了该选项,会依照 6.6《别名》所描述的方式扩展别名。该项在交互模式下默认是开启的。

extdebug

如果在 shell 调用时,或在 shell 启动文件中开启此项,则在 shell 启动前安排执行 debugger 配置文件,其等同于 Bash 使用“—debugger”选项。如果在调用之后开启该项,则开启 debugger 的使用行为意图:

  1. 在使用带有“-F”选项的内建命令“declare”显示函数名时,在其后显示该函数所在的源文件名和相应的所在行数。

  2. 如果由 DEBUG 捕获器运行的命令返回一个非零值时,将跳过下一条命令不予执行。

  3. 如果由 DEBUG 捕获器运行的命令返回值为 2,并且 shell 正执行于一个子任务(由内建命令“.”或 source 执行的函数或脚本)中,则 shell 模拟调用 return。

  4. 变量 BASH_ARGC 和 BASH_ARGV 参照 5.2《Bash 变量》所描述的说明进行更新。

  5. 开启函数追踪:命令替换、shell 函数和使用“( command )”方式调用的子 shell 都继承 DEBUG 和 RETURN 捕获器。

  6. 开启报错追踪:命令替换、shell 函数和使用“( command )”方式调用的子 shell 都继承 ERR 捕获器。

extglob

如果开启了该选项,将开启在 3.5.8.1《样式匹配》中描述的扩展样式匹配特性。

extquote

如果开启了该选项,在双引号括起来的“${parameter}”扩展中执行“$'string'”和“$"string"”引用。该选项默认开启。

failglob

如果开启了该选项,在文件名扩展期间匹配文件名失败的样式会在扩展报错中显示。

force_fignore

如果开启了该选项,当执行单词补全时,包含由 shell 变量 FIGNORE 所指定后缀的单词将被忽略,即使该单词是唯一的补全选项。详情参见 5.2《Bash 变量》中关于 FIGNORE 的描述。该项默认是开启的。

globasciiranges

如果开启了该选项,在进行匹配比较时,在样式匹配的中括号表达式中的范围表达式的行为就像在传统 C 语言区域中一样。也就是说,当前语言区域的校对序列不会在当前匹配中生效,所以不会在“A”和“B”之间校对到“b”,并且大写和小写 ASCII 字符会在一起校对。

globstar

如果开启了该选项,在文件名扩展上下文中的样式“**”将匹配到所有的文件和零个或多个目录及子目录。如果样式后面跟随着一个“/”,则只会匹配目录及子目录。

gnu_errfmt

如果开启了该选项,shell 的报错信息会使用标准 GNU 报错格式书写。

histappend

如果开启了该选项,当 shell 退出时,命令历史列表将追加到变量 HISTFILE 所指定的文件中去,而不是覆盖这个文件。

histreedit

如果开启了该选项,并且使用了 Readline,则用户可得到重新编辑一个失败命令历史替换的机会。

histverify

如果开启了该选项,并且使用了 Readline,命令历史替换的结果不会立即传递给 shell 分析器。作为代替,结果行被加载到 Readline 编辑缓冲中,并允许进一步的修改。

hostcomplete

如果开启了该选项,并且使用了 Readline,当一个单词中包含了一个“@”符号并进行补全操作时(参见 8.4.6《用于补全的命令》),Bash 会试图进行主机名补全操作。该项默认开启。

huponexit

如果开启了该选项,当一个交互式 shell 退出时,Bash 将向所有作业发出 SIGHUP 信号。

inherit_errexit

如果开启了该选项,命令替换继承 errexit 选项的值,而不是在子 shell 环境中释放它。该项在 POSIX 模式下是开启的。

interactive_comments

在交互模式 shell 中允许在第一个单词之前出现“#”。这会使该单词及该行后面的字符都会被忽略。该项默认开启。

lastpipe

如果开启了该选项,并且作业控制没有激活的话,shell 在当前环境中运行管道中最后一条命令不会在后台执行。

lithist

如果开启了该选项,并且也开启了 cmdhist 选项,保存到命令历史中的多行命令会使用换行进行分隔,而不是尽可能使用分号代替。

localvar_inherit

如果开启了该选项,在任意新值分配给本地变量之前,其会继承自上一作用域中相同名称的变量的值和属性。但不会继承“nameref”属性。

localvar_unset

如果开启了该选项,在上一函数作用域中调用“unset”释放本地变量时会先标记它们,这样直到该函数返回,再查打到这些变量进行释放。这等同于在当前函数作用域中释放本地变量的行为。

login_shell

如果 shell 作为登录 shell(参见 6.1《调用 Bash》)启动,则 shell 设置此项为开启状态。该值是不可改变的。

mailwarn

如果开启了该选项,自上一次邮件检查后,当 Bash 为了检查邮件访问了一个文件,会显示“The mail in mailfile has been read”这条消息。

no_empty_cmd_completion

如果开启了该选项,并且使用了 Readline,当试图在一空行中进行补全操作时,Bash 不会为了可能的补全操作来试图搜索变量 PATH。

nocaseglob

如果开启了该选项,在 Bash 执行文件名扩展时,会使用大小写不敏感方式对文件名进行匹配。

nocasematch

如果开启了该选项,Bash 在使用 case 命令或“[[”条件命令执行匹配时,或执行样式替换的单词扩展时,或在作为可编程补全的一部分的可行补全过滤操作时,会使用大小写不敏感进行样式匹配。

nullglob

如果开启了该选项,Bash 允许未匹配到任何文件的文件名样式扩展为一个空字符串,而不是扩展为其本身。

progcomp

如果开启了该选项,则开启可编程补全工具(详见 8.6《可编程补全》)。该项默认开启。

progcomp_alias

如果开启了该选项,并且开启了可编程补全,Bash 视一个没有任何补全可能的命令名为一个可行别名并试图进行别名扩展。如果其果真是别名,Bash 试图使用从扩展的别名生成的命令单词进行可编程补全操作。

promptvars

如果开启了该选项,在参数扩展、命令替换、算术扩展和引用移除的扩展之后按 6.9《提示控制》中所描述的出现提示字符串。该项默认开启。

restricted_shell

如果 shell 启动进入受限模式(参见 6.10《Shell 受限模式》),则设置此项开启。该项不能被修改。当执行启动文件时,该项不能被重置。但允许启动文件获取 shell 是否是在受限模式中。

shift_verbose

如果开启了该选项,当内建命令“shift”的移位数量超出了位置参数的个数时,会打印出错信息。

sourcepath

如果开启了该选项,内建命令“source”会使用变量 PATH 的值进行目录查找,用于查找作为“source”参数的文件位置。该项默认开启。

xpg_echo

如果开启了该选项,内建命令“echo”默认扩展反斜线转义序列。