set
and shopt
are both shell builtins that control various options. I often forget which options are set by which command, and which option sets/unsets (set -o/+o
, shopt -s/-u
). Why are there two different commands that seemingly do the same thing (and have different arguments to do so)? Is there any easy way/mnemonic to remember which options go with which command?
7 Answers
As far as I know, the set -o
options are the ones that are inherited from other Bourne-style shells (mostly ksh), and the shopt
options are the ones that are specific to bash. There's no logic that I know of.
-
1
-
12Well, there are
set -o
options likeposix
/physical
/interactive-comments
that are not inksh
, andshopt
ones that are in other shells includingksh
for some likelogin_shell
/nullglob
. Like you say, there's no logic. It was probably the idea at the start (that SHELLOPTS would be the standard ones, and BASHOPTS the bash specific ones), but that got lost along the way, and now it just ends up being annoying and a UI design fiasco. Commented Jan 25, 2018 at 13:05
The difference is in the changed environment variable used by bash. Setting with the set
command results in $SHELLOPTS
. Setting with the shopt
command results in $BASHOPTS
.
-
22Ugh! That is even more confusing. My brain wants to associate
shopt
with $ SHELLOPTS rather than $ BASHOPTS. Commented Mar 22, 2016 at 16:17
set
is POSIX 7: set - set or unset options and positional parameters | pubs.opengroup.orgshopt
is not: Shell & Utilities: Detailed Toc | pubs.opengroup.org
Probably linked to the history mentioned by @Gilles.
Easy but lost in history. The set
command was used to modify the command line environment of the Bourne shell on Unix, /bin/sh
. (Prior Unix shells that occupied the /bin/sh
position did not have a set
command at all.) Then as various Unix versions evolved, and new shell flavors were added, people realized that they needed to be able to change more (environment) things in order to keep shell scripting compatible. At that time Bash (the Bourne Again shell) got very popular and the additional shell options was needed, introducing shopt
.
You can actually see these compatibility attempts in the shopt
command.
$ shopt
autocd off
cdable_vars off
cdspell off
checkhash off
checkjobs off
checkwinsize off
cmdhist on
compat31 off
compat32 off
compat40 off
compat41 off
compat42 off
complete_fullquote on
direxpand off
dirspell off
dotglob off
execfail off
expand_aliases on
extdebug off
extglob off
extquote on
failglob off
force_fignore on
globstar off
globasciiranges off
gnu_errfmt off
histappend on
histreedit off
histverify off
hostcomplete on
huponexit off
interactive_comments on
lastpipe off
lithist off
login_shell on
mailwarn off
no_empty_cmd_completion off
nocaseglob on
nocasematch off
nullglob off
progcomp on
promptvars on
restricted_shell off
shift_verbose off
sourcepath on
xpg_echo off
But not in the set
command.
$ set -o
allexport off
braceexpand on
emacs on
errexit off
errtrace off
functrace off
hashall on
histexpand on
history on
igncr off
ignoreeof off
interactive-comments on
keyword off
monitor on
noclobber off
noexec off
noglob off
nolog off
notify off
nounset off
onecmd off
physical off
pipefail off
posix off
privileged off
verbose off
vi off
xtrace off
The set
command has several functions, and does not just do one thing. The Bourne Again shell's shopt
command in contrast only deals with shell options; one cannot accidentally mistype and end up setting a positional parameter or a shell variable instead. Other shells do not have a shopt
command, but the Z shell similarly has setopt
and unsetopt
commands that only deal in shell options.
The aforegiven long-form options (to set -o
) were also an innovation with respect to the Bourne shell that was added to the Bourne Again shell (and to others like the Z shell, Almquist shell, Korn shell, and Watanabe shell). The set -o
mechanism with long-form options is in the Single Unix Specification, although it only has a few of the options that real shells actually have.
Long-form options won't be found in the descendants of the Bourne shell, such as the Heirloom Bourne shell, which commercial Unix vendors never adjusted to be POSIX-conformant. At the time, the C shell, and later the Korn shell, were seen as the places to go for innovative new features; and the Bourne shell largely ossified in the early 1980s.
As well as preventing typing mistakes from accidentally doing something else than setting shell options, another feature of the Bourne Again shell's shopt
command is that it is more aligned with the "getopt" conventions that had been developed at the time, but that post-dated the Bourne shell. Unlike the set
command with +
and -
, the only option-introducer character in the shopt
command is -
, and the distinction between setting and unsetting is -s
versus -u
.
Summary
set -o
/set +o
is the Single Unix Specification conformant command. Use it where that is important, albeit that you will also have to restrict yourself to a subset of whatset -o
/set +o
is capable of.shopt
is the command that cannot accidentally be mistyped to do something other than affect shell options, and does only one thing, but is a Bashism. Use it if you prefer the modern conventional "getopt" syntax that took hold in later years. And remember that the fallback is to try with and without its-o
option to pick the desired option set.
-
3
set
as a way to set options wasn't in the original Unix shells, it was introduced by the Bourne shell in the late 70s.set -o name
itself was added later by the Korn shell, specified but optional in POSIX, still not supported by "modern" versions of the Bourne shell like the/bin/sh
of Solaris 10. Commented Aug 23, 2016 at 14:00 -
-
From the book "Linux Shell Scripting with Bash", p 63:
Historically, the
set
command was used to turn options on and off. As the number of options grew,set
became more difficult to use because options are represented by single letter codes. As a result, Bash provides theshopt
(shell option) command to turn options on and off by name instead of a letter. You can set certain options only by letter. Others are available only under theshopt
command. This makes finding and setting a particular option a confusing task.
-
5shouldn't
shopt
encompass allset
varaibles? that way, new scripts can useshopt
andset
would be kept for compatibility. Commented Jul 3, 2022 at 11:09
set
originates from the bourne shell (sh) and is part of the POSIX standard, shopt
is however not and is bourne-again shell (bash) specific:
0 sjas@ssg 14:31:45 ~
set | grep -e SHELLOPTS -e BASHOPTS
BASHOPTS=checkwinsize:cmdhist:complete_fullquote:dotglob:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:progcomp:promptvars:sourcepath
SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
0 sjas@ssg 14:31:51 ~
shopt | column -t | grep -v off
checkwinsize on
cmdhist on
complete_fullquote on
dotglob on
expand_aliases on
extglob on
extquote on
force_fignore on
histappend on
interactive_comments on
progcomp on
promptvars on
sourcepath on
0 sjas@ssg 14:31:57 ~
set -o | column -t | grep -v off
braceexpand on
emacs on
hashall on
histexpand on
history on
interactive-comments on
monitor on
0 sjas@ssg 14:37:41 ~
sh
$ set -o
Current option settings
errexit off
noglob off
ignoreeof off
interactive on
monitor on
noexec off
stdin on
xtrace off
verbose off
vi off
emacs off
noclobber off
allexport off
notify off
nounset off
priv off
nolog off
debug off
$ shopt
sh: 3: shopt: not found
$
It looks like "set" options are inherited by subshells and shopts are not.
-
Nice catch. I wonder whether this is an intentional choice or a side-effect.– KevinCommented Jan 5, 2013 at 19:09
-
2@user29778 At least under bash 4.1.5(1) the options set with
set
are not inherited by subshells.Bothset
andshopt
options are not inherited by subshells.– MartinCommented May 7, 2013 at 22:13 -
1Can you point to the documentation that describes the inheritance characteristics of both
set
andshopt
? Commented Jul 3, 2015 at 1:12 -
11Both
set -o
andshopt
options are inherited by subshells ((...)
,$(...)
, pipeline components). Whether they are inherited by otherbash
invocations depends on whetherSHELLOPTS
orBASHOPTS
are in the environment or not. Commented Aug 23, 2016 at 13:47
help set
andhelp shopt
to verify that even their authors think they do the same thing.set
is ambiguously described as both "Set or unset values of shell options and positional parameters." and then "Change the value of shell attributes and positional parameters, or display the names and values of shell variables."