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.
- 1Any documentation which shows
shoptis inherited ?Felipe Alvarez– Felipe Alvarez2015-07-03 01:13:04 +00:00Commented Jul 3, 2015 at 1:13 - 13Well, there are
set -ooptions likeposix/physical/interactive-commentsthat are not inksh, andshoptones that are in other shells includingkshfor 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.Stéphane Chazelas– Stéphane Chazelas2018-01-25 13:05:46 +00:00Commented 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.
- 26Ugh! That is even more confusing. My brain wants to associate
shoptwith $ SHELLOPTS rather than $ BASHOPTS.Bruno Bronosky– Bruno Bronosky2016-03-22 16:17:04 +00:00Commented Mar 22, 2016 at 16:17
setis POSIX 7: set - set or unset options and positional parameters | pubs.opengroup.orgshoptis 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 +ois 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 +ois capable of.shoptis 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-ooption to pick the desired option set.
- 3
setas 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 nameitself 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/shof Solaris 10.Stéphane Chazelas– Stéphane Chazelas2016-08-23 14:00:18 +00:00Commented Aug 23, 2016 at 14:00 - I have learned something new. Thanks, archeology!:)conny– conny2023-02-16 04:36:44 +00:00Commented Feb 16, 2023 at 4:36
- The best answer here, IMOCertainPensioner– CertainPensioner2023-06-27 18:52:14 +00:00Commented Jun 27, 2023 at 18:52
From the book "Linux Shell Scripting with Bash", p 63:
Historically, the
setcommand was used to turn options on and off. As the number of options grew,setbecame 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 theshoptcommand. This makes finding and setting a particular option a confusing task.
- 6shouldn't
shoptencompass allsetvaraibles? that way, new scripts can useshoptandsetwould be kept for compatibility.ychaouche– ychaouche2022-07-03 11:09:48 +00:00Commented 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.Kevin– Kevin2013-01-05 19:09:01 +00:00Commented Jan 5, 2013 at 19:09
- 2@user29778 At least under bash 4.1.5(1) the options set with
setare not inherited by subshells.Bothsetandshoptoptions are not inherited by subshells.Martin– Martin2013-05-07 22:13:41 +00:00Commented May 7, 2013 at 22:13 - 1Can you point to the documentation that describes the inheritance characteristics of both
setandshopt?Felipe Alvarez– Felipe Alvarez2015-07-03 01:12:13 +00:00Commented Jul 3, 2015 at 1:12 - 12Both
set -oandshoptoptions are inherited by subshells ((...),$(...), pipeline components). Whether they are inherited by otherbashinvocations depends on whetherSHELLOPTSorBASHOPTSare in the environment or not.Stéphane Chazelas– Stéphane Chazelas2016-08-23 13:47:33 +00:00Commented Aug 23, 2016 at 13:47
help setandhelp shoptto verify that even their authors think they do the same thing.setis 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."