De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.

Desvendando o Poder do Comando shopt no Bash

Colaboração: Julio Cezar Neves

Data de Publicação: 31 de julho de 2025

Bem-vindo a este guia abrangente sobre as opções do comando shopt no Bash, uma ferramenta essencial para personalizar e otimizar seu ambiente de linha de comando. O shopt (shell options) permite ativar ou desativar uma variedade de funcionalidades que controlam o comportamento do seu shell, desde a forma como ele lida com o histórico de comandos e a autocompleção até a expansão de curingas e aliases.

Este documento detalha cada uma das opções mais relevantes do shopt, fornecendo definições claras, o status padrão de cada uma e, o mais importante, exemplos práticos que demonstram como elas afetam a sua interação diária com o Bash. Ao explorar estas configurações, você descobrirá como aprimorar sua produtividade, evitar erros comuns e adaptar o terminal às suas necessidades específicas.

Seja você um iniciante buscando entender melhor seu shell ou um usuário avançado procurando refinar suas configurações, este material serve como um recurso valioso para desmistificar o shopt e capacitá-lo a ter um controle ainda maior sobre seu ambiente de trabalho no Linux e sistemas Unix-like.

Então, vamos lá!

cdspell

Definiçao: O Bash corrige automaticamente pequenos erros de digitação em diretórios ao usar cd

Status default: off

Exemplos

$ cd /rin
bash: cd: /rin: Arquivo ou diretório inexistente
$ shopt -s cdspell
$ cd /rin
/bin

checkjobs

Definição: Os precavidos ativam esta opção em tempo de login (inserindo shopt -s checkjobs no .bashrc). Sua função é verificar se existem processos em segundo plano (background) antes de sair do Shell e exibe um aviso se houver jobs pendentes.

Status default: off

Exemplos

$ shopt -s checkjobs  # Ativa a opção
$ sleep 60 &          # Executa um job em segundo plano
$ exit                # Tenta sair do shell
There are running jobs.
jobs: [1]  + running    sleep 60

Esta mensagem não teria ocorrido, caso a opção não tivesse sido ligada.

cmdhist

Definição: Armazena comandos multilinha (como loops ou if) como uma única entrada no histórico.

Status default: on

Exemplos

$ shopt s cmdhist      # Ativa a opção
$ for i in {1..3}; do  # Digitando um comando multi-linha
>     echo "Número: $i"
> done
> history | tail -n 3  # Listando as 3 últimas linhas do histórico
 0010  for i in {1..3}; do echo "Número: $i"; done 

O comando inteiro é salvo como uma única linha no histórico. 0010 é o número da linha no histórico de comandos.

$ shopt -u cmdhist  # Desativa a opção
$ for i in {1..3}; do  # Digitando um comando multi-linha
>     echo "Número: $i"
> done
$ history | tail -n 5  # Verifica o histórico
0011  for i in {1..3}; do
0012      echo "Número: $i"
0013  done
complete_fullquote

complete_fullquote

Definição: Controla se o Bash deve realizar quoting completo (com aspas) em cadeias durante a autocompletar (tab completion), especialmente para proteger caracteres especiais (como espaços, $, !, etc.).

Status default: on

Exemplos

$ shopt -s complete_fullquote   # Ativa opção (quase sempre o padrão)
$ > "arquivo com espaços.txt"   # Cria um arquivo com espaços no nome

Fazendo no terminal:

$ cat arq                  # Para autocompletar

O Bash completa como:

$ cat 'arquivo com espaços.txt' # Nome entre aspas simples

Vamos desligar a opção e fazer o mesmo:

$ shopt -u complete_fullquote   # Desativa a opção
$ > "arquivo com espaços.txt"   # Mesmo arquivo

Fazendo no terminal:

$ cat arq                  # Para autocompletar

O Bash completa como:

$ cat arquivo\ com\ espaços.txt # Nome escapado com barra invertida
dotglob

dotglob

Definição: Inclui arquivos ocultos (iniciados com .) na expansão de curingas (*, ?, etc.).

Status default: off (arquivos ocultos são ignorados por padrão).

Exemplos

$ shopt -u dotglob	# Estado default
$ ls * | head -3
ChangeLog12Edicao.odt
Expr.odt
Shell_11edicao.odt

Fazendo o mesmo com a facilidade habilitada:

$ shopt -s dotglob
$ ls * | head -3
.bash_history
.bash_logout
ChangeLog12Edicao.odt

Mais um exemplo:

$ shopt -u dotglob    # Desabilitando a opção. Este é o default
$ ls *bash*
ls: impossível acessar *bash*: Arquivo ou diretório inexistente

Vamos fazer o mesmo com a opção habilitada:

$ shopt -s dotglob    # Habilitado a opção
$ ls *bash*
.bash_history  .bash_logout  .bashrc

Expand_aliases

Definição: Controla se aliases definidos no Shell serão expandidos durante a execução de scripts ou no modo interativo.

Status default: on (ligado) no modo interativo, off (desligado) em scripts.

Exemplos

Suponha que você precisa incluir no seu relatório uma listagem longa (ls -l) de certos arquivos, mas seu ls está colorido, porque:

$ alias ls
alias ls='ls –color=auto'

Ou seja, a lista que preciso sairá colorida, então prefiro executar um:

$ shopt -u expand_aliases

Antes de fazer o ls -l, de forma tirar as cores da lista longa dos arquivos para poder copiar+colar no relatório.

Dicas:

1. Aliases são expandidos no momento da leitura (não durante a execução) e o Bash sempre lê pelo menos uma linha completa de entrada e todas as linhas que compõem um comando composto antes de executar qualquer um dos comandos nessa linha ou no comando composto. Portanto, um alias que aparece na mesma linha que outro comando, não entra em vigor até que a próxima linha de entrada seja lida. A decorrência disso é que no caso que estamos analisando, aparentemente poderíamos tentar agrupar tudo num subshell, fazendo:

$ (shopt -u expand_aliases; ls)  # Parenteses criam subshells

Porém o alias do ls não seria desfeito, por estar na mesma linha, mas o próximo ls, não seria a cores.

2. Se precisar de apelidos mais robustos, prefira funções Shell (ex.: meuf() { ... }).

extglob

Definição: Se a opção de Shell extglob estiver habilitada usando o builtin shopt (shopt -s extglob), o Shell reconhecerá vários operadores de padrões estendidos. Na descrição a seguir, LISTA é uma lista de um ou mais padrões separados por uma barra vertical (|). Os padrões estendidos a seguir, podem ser usados em qualquer local onde também o sejam os coringas, isto é, na expansão de nomes de arquivos, nos comandos test e case e nas Expansões de Parâmetros.

Coringa Uso
?(LISTA) Corresponde a zero ou uma ocorrência dos padrões fornecidos.
*(LISTA) Corresponde a zero ou mais ocorrências dos padrões fornecidos.
+(LISTA) Corresponde a uma ou mais ocorrências dos padrões fornecidos.
@(LISTA) Corresponde a um dos padrões fornecidos.
!(LISTA) Corresponde a qualquer coisa, exceto um dos padrões fornecidos.

Status default: on (ligado) no modo interativo, off (desligado) em scripts.

Exemplos com ls

$ shopt -s extglob
# Listar todos os arquivos exceto .txt
$ ls !(*.txt)
# Listar arquivos que começam com a ou b
$ ls @(a|b)*
# Listar arquivos com 1 ou mais dígitos no nome
$ ls +([0-9])*
# Listar arquivos que são .jpg ou .png mas não .thumb.jpg
$ ls *.@(jpg|png) !(*.thumb.*)

Exemplos com test (condicionais)

# Verificar um horário está no formato HH:MM:
$ shopt -s extglob
$ [[ $H == @(?([01])[0-9]|2[0-3]):?([0-5])[0-9] ]] &&
>     echo Horário OK ||
>     echo Horário NOK

Nesse caso usamos o ?([01]) na definição da hora e o ?([0-5]) na definição do minuto, para o zero em ambos fosse opcional, de forma a casar tanto com 1:2 como com 01:02.

# Verificar se NÃO é um arquivo de sistema
$ if [[ $arquivo == !(*.sys|system.*) ]]; then
>     echo "Arquivo não é de sistema"
> fi
# Para saber se o conteúdo de uma variável é somente números
$ [[ -z ${Var//[0-9]/} ]] && echo Numérico

Fazendo assim, trocamos todos (//) os números [0-9] por nada, pois após a 3ª barra (/) está vazio (se não houvesse esta última barra, o efeito seria o mesmo. Coloque-a para efeito didático).

Exemplos com case

$ shopt -s extglob
$ read -p "Digite uma opção: " Opc
$ case ${Opc} in  #  A Expansão de Parâmetros  coloca
>                   #+ o conteúdo de $Opc em maiúscula.
>     @(S?(im)|Y?(ES)) echo.Aceitou   ;;
>     @N?(ão|O))       echo recusou ;;
>     *)               echo Informe s, sim, y ou yes
> esac

Para vermos se a variável $Var é um número inteiro, ou um número real (o que tem vŕgula ou ponto decimal) podemos fazer:

$ case $Var in
>     +([0-9]))         echo Inteiro;;
>     +([0-9])*[0-9.,]) echo Real;;
>    *)                 echo Não é numérico;;
> esac

Exemplos com Expansões de Parâmetros

Suponha que você queira tirar brancos e <TAB>s repetidos de um texto. Algo assim:

function LimpaTexto
{
        #  Limpa espaços e **s** à esquerda
        #+ e à direita da cadeia passada
    : "${1##+([[:space:]])}"   # Limpa o máximo à esquerda
    echo ${_%%+([[:space:]])}  # Limpa o máximo à direita
}; export -f LimpaTexto

Na primeira linha, o 1## corta a maior ocorrência à esquerda que case com +([[:space:]]), que significa um ou mais espaços ou <TAB>s, A variável $_, que na linha seguinte será, da mesma forma, suprimida dos espaços e <TAB>s à direita e esta variável ($_) sempre conterá o último parâmetro da última instrução.

Vamos entendê-lo linha a linha supondo que passei " uma linha cheia de espaços e <TAB>s " como parâmetro da função:

$ set "   uma    linha  cheia de espaços e  **s**      "
$ : "${1##+([[:space:]])}"   # Limpa o máximo à esquerda
$ echo "[$_]"
[uma    linha   cheia de espaços e  **s**      ]

Repare que:

O comando : não fez nada, mas permitiu que a linha fosse resolvida, expandindo os parâmetros;

O ${1##+([[:space:]])} cortou à esquerda todos os espaços e <TAB>s (+([[:space:]]));

A variável $_ ficou com o último parâmetro (que foi gerado pelo comando :).

Vamos agora executar a linha seguinte, mas como ela usará a variável $_, que foi alterada quando colocamos a saída entre um par de colchetes ([...]) devemos novamente executar a anterior só para restautar o $_ sem os colchetes ([...]).

$ : "${1##+([[:space:]])}"     # Repetindo para restaurar $_
$ echo [${_%%+([[:space:]])}]  # Limpa o máximo à direita
[uma linha cheia de espaços e **s**]

As outras <TAB>s e espaços que existiam, por fazerem parte de $IFS, o próprio Shell os apresentou como um único espaço em branco.

extquote

Definição: Se definido, as sequências de escape da forma $'CADEIA' e $"CADEIA" serão executadas dentro das Expansões de Parâmetros desde que toda ela esteja entre aspas.

Status default: on

Exemplos

$ Var="cad1 cad2 cad3"
$ shopt -u extquote	# Desligando o extquote
$ echo "${Var// /$'\n'}"	# Não vai funcionar
cad1$\ncad2$\ncad3
$ shopt -s extquote	# Ligando-o
$ echo "${Var// /$'\n'}"	# Assim funciona
cad1
cad2
cad3

Mas essas aspas externas, são só para que os <ENTER>s que fazem parte da $IFS padrão não sejam vistos pelo Shell e transformados em espaços em branco, comprove isso:

$ Var=${Var// /$'\n'}	# Sem as aspas externas
$ echo $Var
cad1 cad2 cad3
$ echo "$Var"	# Mas usando as aspas para inibir o efeito IFS
cad1
cad2
cad3

Agora que $Var está dividida em linhas, para apagar a primeira, devemos matar tudo antes do primeiro <ENTER>, então podemos fazer:

$ echo ${Var#*$'\n'}	# Sem as aspas os ****s viram espaços
cad2 cad3
$ echo "${Var#*$'\n'}"	# Dessa forma mantemos os ****s
cad2
cad3



Veja a relação completa dos artigos de Julio Cezar Neves