Eu trabalho em um ambiente relativamente heterogêneo onde posso estar executando diferentes versões do Bash em diferentes nós HPC, VMs ou minha estação de trabalho pessoal. Como coloquei meus scripts de login em um repositório Git, gostaria de usar o mesmo (ish) .bashrc
em geral, sem muita bagunça do tipo "se este host, então...".
Eu gosto do comportamento padrão do Bash ≤ 4.1 que se expande cd $SOMEPATH
ao cd /the/actual/path
pressionar a Tabtecla. No Bash 4.2 e acima, você precisaria shopt -s direxpand
reativar esse comportamento, e isso não ficou disponível até 4.2.29 . Este é apenas um exemplo; shopt
outra opção possivelmente relacionada complete_fullquote
(embora eu não saiba exatamente o que ela faz) também pode ter alterado o comportamento padrão na v4.2.
No entanto, direxpand
não é reconhecido por versões anteriores do Bash e, se eu tentar shopt -s direxpand
no meu .bashrc
, isso resultará em uma mensagem de erro sendo impressa no console toda vez que eu efetuar login em um nó com um Bash mais antigo:
-bash: shopt: direxpand: invalid shell option name
O que eu gostaria de fazer é envolver uma condicional shop -s direxpand
para habilitar essa opção no Bash > 4.1 de maneira robusta, sem irritar as versões mais antigas do Bash ( ou seja , não apenas redirecionar a saída de erro para /dev/null
).
Não vejo o que há de errado em redirecionar erros para arquivos
/dev/null
. Se você quiser que seu código seja robustoset -e
, use o idioma comum… || true
:Se você quiser executar algum código de fallback se a opção não existir, use o status de retorno de
shopt
:Mas se você realmente não gosta de redirecionar o erro, pode usar o mecanismo de conclusão para realizar a introspecção. Isso pressupõe que você não tenha máquinas antiquadas com bash ≤ 2.03 que não tenham conclusão programável.
Esse método evita a bifurcação, que é lenta em alguns ambientes, como o Cygwin. O mesmo acontece com o simples
2>/dev/null
, não acho que você possa superar isso em desempenho.Verifique se
direxpand
está presente na saída deshopt
e habilite-o se estiver:Quando você sabe com certeza que uma
shopt
opção específica está disponível em uma determinada versão principal/secundária/patch do Bash, você pode inspecionar a$BASH_VERSION
variável ou os elementos da$BASH_VERSINFO[]
matriz para habilitá-la condicionalmente.Aqui está um teste para Bash 4.2.29 ou superior, a versão em que
direxpand
foi introduzida pela primeira vez na série 4.2:Editar: Para ser claro, esta é uma solução ridiculamente projetada para simplesmente ignorar uma mensagem de erro proveniente de seus scripts de login, mas eu queria documentá-la independentemente, para minha própria edificação.
Observe as chaves em torno de , que são necessárias, e o uso de e , que fazem comparações léxicas inteiras em vez de (dependentes de localidade). Se não estiver entre aspas, o RHS do operador é tratado como padrões "extglob" dentro do Bash / condicionais, conforme observado aqui , o que faz uma comparação "começa com" mais estética do que um regex faria, IMO.
${BASH_VERSINFO[index]}
-eq
-gt
==
[[
]]
A
$BASH_VERSINFO
matriz contém todas as informações que você veria na saída debash --version
:Quando não está claro na documentação
shopt
em que as versões do Bash foram suportadas ou mudaram seu comportamento, o método proposto por Luciano está correto:...como é a solução proposta por Gilles de simplesmente ignorar o erro (
shopt -s direxpand 2>/dev/null
), e talvez checar$?
se for absolutamente necessário.Referências: 1 , 2 , 3
Leitura relacionada: Set and Shopt - Why Two?