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. 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
.
-
19Ugh! That is even more confusing. My brain wants to associate
shopt
with $ SHELLOPTS rather than $ BASHOPTS. 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 originally used to modify the command line environment of the original unix shells /bin/sh
. Then as various Unix versions evolved, and new shell flavors was 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 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
-
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. 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.
-
shouldn't
shopt
encompass allset
varaibles? that way, new scripts can useshopt
andset
would be kept for compatibility. Jul 3 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.– KevinJan 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.– MartinMay 7, 2013 at 22:13 -
1Can you point to the documentation that describes the inheritance characteristics of both
set
andshopt
? Jul 3, 2015 at 1:12 -
10Both
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. 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."