Até onde eu sei, as opções set -o
são aquelas que são herdadas de outras shells no estilo Bourne (principalmente ksh), e as opções shopt
são aquelas específicas do bash. Não há lógica que eu conheça.
set
e shopt
são ambos internos do shell que controlam várias opções. Muitas vezes esqueço quais opções são definidas por qual comando e, ocasionalmente, qual opção define / desmarca ( set +o/-o
, shopt -s/-u
). Por que existem dois comandos diferentes que aparentemente fazem a mesma coisa (e têm diferentes argumentos para fazer isso)? Existe alguma maneira fácil / mnemônica para lembrar quais opções vão com qual comando?
A diferença está na variável de ambiente alterada usada pelo bash. A configuração com o comando set
resulta em $SHELLOPTS
. A configuração com o comando shopt
resulta em $BASHOPTS
.
set
é POSIX 7: definir ou definir opções e parâmetros posicionais | pubs.opengroup.org
shopt
não é: Shell & Utilitários: Detailed Toc | pubs.opengroup.org
Provavelmente ligado à história mencionada por @Gilles.
Fácil, mas perdido na história. O comando set
foi usado originalmente para modificar o ambiente de linha de comando dos shells unix originais /bin/sh
. Então, como várias versões do Unix evoluíram, e novos sabores do shell foram adicionados, as pessoas perceberam que precisavam ser capazes de mudar mais coisas (do ambiente) para manter o shell script compatível. Naquela época o Bash ficou muito popular e os íons sh ell opt adicionais foram necessários, introduzindo shopt
.
Você pode realmente ver essas tentativas de compatibilidade compat no comando shopt
.
$ 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
Mas não no comando set
.
$ 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
Parece que as opções "set" são herdadas pelos subshells e os shopts não são.
No livro "Linux Shell Scripting com 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.