Je travaille dans un environnement relativement hétérogène où je peux exécuter différentes versions de Bash sur différents nœuds HPC, machines virtuelles ou mon poste de travail personnel. Parce que je mets mes scripts de connexion dans un référentiel Git, je voudrais utiliser le même (ish) à .bashrc
tous les niveaux, sans beaucoup de "si cet hôte, alors ..." - type désordre.
Je comme le comportement par défaut de Bash ≤ 4.1 qui se développe cd $SOMEPATH
en cd /the/actual/path
lorsque vous appuyez sur la Tabtouche. Dans Bash 4.2 et supérieur, vous devrez shopt -s direxpand
réactiver ce comportement, et ce n'est devenu disponible que le 4.2.29 . Ce n'est qu'un exemple, cependant; une autre shopt
option , éventuellement liée , complete_fullquote
(bien que je ne sache pas exactement ce qu'elle fait) peut également avoir changé le comportement par défaut de la v4.2.
Cependant, direxpand
n'est pas reconnu par les versions antérieures de Bash, et si je tente de shopt -s direxpand
mon .bashrc
, qui se traduit par un message d'erreur en cours d' impression à la console à chaque fois que je me connecte à un nœud avec un Bash plus:
-bash: shopt: direxpand: invalid shell option name
Ce que j'aimerais faire, c'est encapsuler un conditionnel shop -s direxpand
pour activer cette option sur Bash> 4.1 de manière robuste, sans frotter les anciennes versions de Bash ( c'est -à- dire , pas seulement rediriger la sortie d'erreur vers /dev/null
).
la source
.bashrc
. Je voulais toujours un enregistrement de la façon d'utiliser$BASH_VERSINFO
pour interroger la version majeure / mineure du shell en cours d'exécution, pour ma propre édification, c'est pourquoi j'ai fini de poster ma propre réponse.:)
Réponses:
Vérifiez s'il
direxpand
est présent dans la sortie deshopt
et activez-le s'il est:la source
grep -q '^direxpand\b'
dans le cas où une future version ou fork de bash a une option qui la contient comme sous - chaîne et la supprimedirexpand
. Peu probable dans ce cas spécifique, mais il ne coûte pas cher d'être robuste.[ -z "$(shopt -po direxpand 2>&-)" ] || shopt -s direxpand
. Plus de problèmes d'expression régulière! :-)[ -n "blah" ] && shopt blah
la façon dont vous l'exprimez, vous dites "si direxpand n'est pas pris en charge, alors ne faites pas cette chose".set -e
en haut, j'ai donc tendance à utiliser une logique de raccourci de cette façon.Je ne vois pas ce qui ne va pas avec la redirection des erreurs
/dev/null
. Si vous voulez que votre code soit robusteset -e
, utilisez l'idiome commun… || true
:Si vous souhaitez exécuter du code de secours si l'option n'existe pas, utilisez l'état de retour de
shopt
:Mais si vous n'aimez pas vraiment rediriger l'erreur, vous pouvez utiliser le mécanisme de complétion pour effectuer une introspection. Cela suppose que vous n'avez pas de machines obsolètes avec bash ≤ 2.03 qui n'avaient pas de fin programmable.
Cette méthode évite le bifurcation, qui est lent sur certains environnements tels que Cygwin. Il en va de même pour le simple
2>/dev/null
, je ne pense pas que vous pouvez battre cela sur la performance.la source
compgen
proposition. C'est des trucs de niveau universitaire juste là! Éviter la redirection vers/dev/null
n'est qu'une préférence personnelle. J'aime demander la permission au lieu du pardon, si cela a du sens?:)
compgen -A shopt -X ...
cela signifiait.compgen
cette méthode sur Unix et Linux , je ne sais pas qui l'a proposé en premier. (J'ai cessé d'utiliser bash comme shell principal avant qu'il ne soit programmé.) En programmation, c'est généralement une mauvaise idée de demander la permission car il y a un risque que la vérification des permissions ne corresponde pas à ce que vous faites réellement, soit à cause d'un codage erreur (où vous ne vérifiez pas vraiment ce que vous pensez vérifier) ou parce que ce que vous avez vérifié a changé avant de l'utiliser .Lorsque vous savez avec certitude qu'une
shopt
option spécifique est disponible dans une certaine version majeure / mineure / de patch de Bash, vous pouvez inspecter la$BASH_VERSION
variable ou les éléments du$BASH_VERSINFO[]
tableau afin de l'activer conditionnellement.Voici un test pour Bash 4.2.29 ou supérieur, la version où a
direxpand
été introduite pour la première fois dans la série 4.2:Edit: Pour être clair, il s'agit d'une solution ridiculement surdimensionnée pour ignorer simplement un message d'erreur provenant de vos scripts de connexion, mais je voulais le documenter malgré tout, pour ma propre édification.
Notez les accolades autour , qui sont obligatoires, et l'utilisation de et , qui font des comparaisons lexicales entières plutôt que (dépendantes des paramètres régionaux). S'il n'est pas cité, le RHS de l' opérateur est traité comme des motifs "extglob" dans Bash / conditionals, comme indiqué ici , ce qui rend une comparaison "commence par" plus esthétique qu'un regex, IMO.
${BASH_VERSINFO[index]}
-eq
-gt
==
[[
]]
Le
$BASH_VERSINFO
tableau contient toutes les informations que vous verriez dans la sortie debash --version
:Lorsqu'il n'est pas clair dans la documentation pour
shopt
laquelle les versions de Bash ont été prises en charge ou ont changé leur comportement, la méthode proposée par Luciano est très bien:... tout comme la solution proposée par Gilles d'ignorer simplement l'erreur (
shopt -s direxpand 2>/dev/null
), et peut-être de vérifier$?
si c'est absolument nécessaire.Références: 1 , 2 , 3
Lecture connexe: Set and Shopt - Why Two?
la source
if [[ $BASH_VERSION > 4.3 ]];
(qui correspond4.3.0
,5.0
etc., mais aussi4.3.0-alpha
. Je ne sais pas si le fait ultérieur compte.)direxpand
option est en effet disponible pour Bash 4.2, cependant; J'ai vérifié cela avec une image Docker en v4.2.53 en exécutantdocker run --rm bash:4.2 bash -c shopt | grep direxpand
(et, pour faire bonne mesure, qu'elle n'est en effet pas disponible en v4.1.17 en exécutantdocker run --rm bash:4.1 bash -c shopt | grep direxpand
).4.2.0
et suis tombé sur le fait que cela ne fonctionnait pas là-bas. Le journal des modifications mentionne également son ajoutbash-4.3-alpha
. Je suppose alors qu'il faudrait vérifier${BASH_VERSINFO[2]}
pour être exact à ce sujet, mais je ne sais pas quel point de sortie l'a ajouté ...