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?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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.
Method 2
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.
Method 3
-
setis POSIX 7: set – set or unset options and positional parameters | pubs.opengroup.org -
shoptis not: Shell & Utilities: Detailed Toc | pubs.opengroup.org
Probably linked to the history mentioned by @Gilles.
Method 4
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
Method 5
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.
Method 6
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 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="10637a716350636377">[email protected]</a> 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 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="196a73786a596a6a7e">[email protected]</a> 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 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b8cbd2d9cbf8cbcbdf">[email protected]</a> 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 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e1928b8092a1929286">[email protected]</a> 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 $
Method 7
It looks like “set” options are inherited by subshells and shopts are not.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0