Trabalho em um ambiente relativamente heterogêneo, onde posso estar executando versões diferentes do Bash em diferentes nós HPC, VMs ou minha estação de trabalho pessoal. Como eu coloquei meus scripts de login em um repositório Git, eu gostaria de usar o mesmo (ish) .bashrc
em geral, sem muitos "se este host, então ..." - confusão do tipo.
I como o comportamento padrão do Bash ≤ 4.1 que se expande cd $SOMEPATH
em cd /the/actual/path
quando pressionando a Tabtecla. No Bash 4.2 e acima, você precisaria shopt -s direxpand
reativar esse comportamento, que não estava disponível até o 4.2.29 . Este é apenas um exemplo; outra shopt
opção possivelmente relacionada complete_fullquote
(embora eu não saiba exatamente o que faz) também pode ter mudado o comportamento padrão na v4.2.
No entanto, direxpand
não é reconhecido pelas versões anteriores do Bash e, se eu tentar shopt -s direxpand
no meu .bashrc
, isso resulta em uma mensagem de erro sendo impressa no console toda vez que eu faço logon em um nó com um Bash mais antigo:
-bash: shopt: direxpand: invalid shell option name
O que eu gostaria de fazer é agrupar uma condição condicional shop -s direxpand
para ativar essa opção no Bash> 4.1 de maneira robusta, sem atrapalhar as versões mais antigas do Bash ( ou seja , não apenas redirecionar a saída de erro para /dev/null
).
fonte
.bashrc
. Eu ainda queria um registro de como usar$BASH_VERSINFO
para interrogar a versão principal / secundária do shell em execução, para minha própria edificação, e é por isso que terminei de postar minha própria resposta.:)
Respostas:
Verifique se
direxpand
está presente na saída deshopt
e ative-o se estiver:fonte
grep -q '^direxpand\b'
, caso alguma versão futura ou fork do bash tenha uma opção que contenha isso como substring e removadirexpand
. Improvável neste caso específico, mas não custa muito para ser robusto.[ -z "$(shopt -po direxpand 2>&-)" ] || shopt -s direxpand
. Não há mais problemas de regex! :-)[ -n "blah" ] && shopt blah
jeito que você diz, você está dizendo "se direxpand não é suportado, então não faça isso".set -e
no topo, então eu costumo usar a lógica de atalho dessa maneira.Não vejo o que há de errado em redirecionar erros para
/dev/null
. Se você deseja que seu código seja robustoset -e
, use o idioma comum… || true
:Se você deseja 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 executar a introspecção. Isso pressupõe que você não possui máquinas antiquadas com bash ≤ 2,03 que não possuem conclusão programável.
Esse método evita a bifurcação, o que é lento em alguns ambientes, como o Cygwin. O mesmo acontece com o direto
2>/dev/null
, não acho que você possa superar isso no desempenho.fonte
compgen
proposta. Isso é coisa de nível do time do colégio ali mesmo! Evitar o redirecionamento para/dev/null
é apenas uma preferência pessoal. Eu gosto de pedir permissão em vez de perdão, se isso faz sentido?:)
compgen -A shopt -X ...
significava.compgen
dessa maneira no Unix e Linux , não sei quem o propôs pela primeira vez. (Parei de usar o bash como meu shell principal antes de ter a conclusão programável.) Na programação, geralmente é uma má idéia pedir permissão porque existe o risco de a verificação de permissão não corresponder ao que você está realmente fazendo, devido a uma codificação erro (onde você não está verificando o que pensa estar verificando) ou porque o que você verificou mudou antes de usá-lo .Quando você tem certeza de que uma
shopt
opção específica está disponível em uma versão principal / secundária / de 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 o Bash 4.2.29 ou superior, a versão em que
direxpand
foi introduzida pela primeira vez na série 4.2:Edit: Para ser claro, esta é uma solução ridiculamente super-projetada para simplesmente ignorar uma mensagem de erro proveniente de seus scripts de login, mas eu queria documentá-la independentemente, para minha própria edição.
Observe as chaves ao redor , que são necessárias e o uso de e , que fazem comparações lógicas de números inteiros em vez de (dependentes do código do idioma). Se não for citado, o RHS do operador é tratado como padrões "extglob" dentro de Bash / condicionais, conforme observado aqui , o que torna uma comparação "estética com" mais estética do que uma regex seria, 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 para
shopt
a qual as versões do Bash foram suportadas ou alteraram seu comportamento, o método proposto por Luciano é bom:... como é a solução proposta por Gilles de apenas ignorar o erro (
shopt -s direxpand 2>/dev/null
) e talvez verificar$?
se é absolutamente necessário.Referências: 1 , 2 , 3
Leitura relacionada: Set and Shopt - Why Two?
fonte
if [[ $BASH_VERSION > 4.3 ]];
(que corresponde4.3.0
,5.0
etc., mas também4.3.0-alpha
não sei se os assuntos de fatos posteriores..)direxpand
opção está realmente disponível para o Bash 4.2; Eu verifiquei isso com uma imagem do Docker na v4.2.53 executandodocker run --rm bash:4.2 bash -c shopt | grep direxpand
(e, para uma boa medida, que de fato não está disponível na v4.1.17 executandodocker run --rm bash:4.1 bash -c shopt | grep direxpand
).4.2.0
e me deparei com o fato de que não funcionava lá. O changelog também menciona que foi adicionadobash-4.3-alpha
. Suponho então que seria preciso verificar${BASH_VERSINFO[2]}
para ser exato sobre isso, mas eu não sei qual ponto de libertação acrescentou que ...