Ich arbeite in einer relativ heterogenen Umgebung, in der ich möglicherweise verschiedene Versionen von Bash auf verschiedenen HPC-Knoten, VMs oder meiner persönlichen Workstation ausführe. Da ich meine Anmeldeskripte in ein Git-Repo eingefügt habe, möchte ich dasselbe (ish) .bashrc
auf der ganzen Linie verwenden, ohne viel Unordnung vom Typ "Wenn dieser Host, dann ...".
Ich mag das Standardverhalten von Bash ≤ 4.1, das cd $SOMEPATH
sich cd /the/actual/path
beim Drücken der TabTaste erweitert. In Bash 4.2 und höher müssten Sie shopt -s direxpand
dieses Verhalten erneut aktivieren, und das wurde erst in 4.2.29 verfügbar . Dies ist jedoch nur ein Beispiel; Eine andere, möglicherweise verwandte shopt
Option complete_fullquote
(obwohl ich nicht genau weiß , was sie tut) hat möglicherweise auch das Standardverhalten in Version 4.2 geändert.
Jedoch direxpand
wird nicht von früheren Versionen von Bash erkannt, und wenn ich versuche, shopt -s direxpand
in meinem .bashrc
, dass die Ergebnisse in einer Fehlermeldung an die Konsole jedes Mal gedruckt wird , ich melden Sie sich an , um einen Knoten mit einem älteren Bash:
-bash: shopt: direxpand: invalid shell option name
Ich möchte eine Bedingung umschließen shop -s direxpand
, um diese Option auf Bash> 4.1 auf robuste Weise zu aktivieren, ohne die älteren Versionen von Bash zu scheuern ( dh nicht nur die Fehlerausgabe an umzuleiten /dev/null
).
quelle
.bashrc
. Ich wollte immer noch eine Aufzeichnung darüber, wie ich$BASH_VERSINFO
die Haupt- / Nebenversion der laufenden Shell für meine eigene Erbauung abfragen kann, weshalb ich meine eigene Antwort fertiggestellt habe.:)
Antworten:
Überprüfen Sie, ob
direxpand
in der Ausgabe von vorhanden ist,shopt
und aktivieren Sie sie, wenn:quelle
grep -q '^direxpand\b'
falls eine zukünftige Version oder Gabel von Bash eine Option hat, die diese als Teilzeichenfolge enthält und entferntdirexpand
. In diesem speziellen Fall unwahrscheinlich, aber es kostet nicht viel, robust zu sein.[ -z "$(shopt -po direxpand 2>&-)" ] || shopt -s direxpand
. Keine Regex-Probleme mehr! :-)[ -n "blah" ] && shopt blah
So wie du es formulierst, sagst du "Wenn direxpand nicht unterstützt wird, dann mach das nicht".set -e
oben, daher verwende ich auf diese Weise eher Abkürzungslogik.Ich sehe nicht, was falsch daran ist, Fehler umzuleiten
/dev/null
. Wenn Sie möchten, dass Ihr Code robust istset -e
, verwenden Sie die allgemeine Redewendung… || true
:Wenn Sie einen Fallback-Code ausführen möchten, wenn die Option nicht vorhanden ist, verwenden Sie den Rückgabestatus von
shopt
:Wenn Sie den Fehler jedoch nicht wirklich umleiten möchten, können Sie den Abschlussmechanismus verwenden, um eine Selbstbeobachtung durchzuführen. Dies setzt voraus, dass Sie keine veralteten Maschinen mit Bash ≤ 2,03 haben, die keine programmierbare Fertigstellung hatten.
Diese Methode vermeidet das Gabeln, das in einigen Umgebungen wie Cygwin langsam ist. Also das einfach funktioniert
2>/dev/null
, ich glaube nicht , dass Sie auf die Leistung schlagen kann.quelle
compgen
Vorschlag. Das ist genau dort Uni-Level-Zeug! Das Vermeiden der Weiterleitung an/dev/null
ist nur eine persönliche Präferenz. Ich bitte lieber um Erlaubnis als um Vergebung, wenn das Sinn macht?:)
compgen -A shopt -X ...
überhaupt bedeutete.compgen
dieser Methode unter Unix und Linux gelesen. Ich weiß nicht, wer sie zuerst vorgeschlagen hat. (Ich habe Bash nicht mehr als Haupt-Shell verwendet, bevor es programmierbar abgeschlossen wurde.) Bei der Programmierung ist es normalerweise eine schlechte Idee, um Erlaubnis zu bitten, da das Risiko besteht, dass die Berechtigungsprüfung aufgrund einer Codierung nicht mit dem übereinstimmt, was Sie tatsächlich tun Fehler (bei dem Sie nicht genau überprüfen, was Sie zu überprüfen glauben) oder weil sich das, was Sie überprüft haben, geändert hat, bevor Sie es verwendet haben .Wenn Sie sicher sind, dass eine bestimmte
shopt
Option in einer bestimmten Haupt- / Neben- / Patch-Version von Bash verfügbar ist, können Sie die$BASH_VERSION
Variable oder die Elemente des$BASH_VERSINFO[]
Arrays überprüfen , um sie bedingt zu aktivieren.Hier ist ein Test für Bash 4.2.29 oder höher, die Version, in der die 4.2-Serie
direxpand
erstmals vorgestellt wurde :Bearbeiten: Um es klar auszudrücken, ist dies eine lächerlich überentwickelte Lösung, um eine Fehlermeldung aus Ihren Anmeldeskripten einfach zu ignorieren, aber ich wollte sie trotzdem für meine eigene Bearbeitung dokumentieren.
Beachten Sie die Klammern um , die sind erforderlich, und die Verwendung von und , die ganzen Zahl zu tun , anstatt (locale abhängig) lexikalische Vergleiche. Wenn nicht notierte, die RHS der ist Betreiber als „extglob“ Muster innerhalb Bash behandelt / conditionals, wie erwähnt hier , die ein ästhetischer „beginnt mit“ Vergleich als ein regex wäre IMO macht.
${BASH_VERSINFO[index]}
-eq
-gt
==
[[
]]
Das
$BASH_VERSINFO
Array enthält alle Informationen, die Sie in der Ausgabe von sehen würdenbash --version
:Wenn es nicht ist , ergibt sich aus der Dokumentation ,
shopt
an der Bash - Version (en) wurde ihr Verhalten unterstützt oder geändert wird , ist das Verfahren von Luciano vorgeschlagen fein:... ebenso wie die von Gilles vorgeschlagene Lösung, den Fehler (
shopt -s direxpand 2>/dev/null
) einfach zu ignorieren und möglicherweise zu prüfen,$?
ob dies unbedingt erforderlich ist.Referenzen: 1 , 2 , 3
Verwandte Lektüre: Set and Shopt - Warum zwei?
quelle
if [[ $BASH_VERSION > 4.3 ]];
(Spiele , die4.3.0
,5.0
etc., aber auch4.3.0-alpha
ich weiß nicht , ob die später tatsächlich Angelegenheiten..)direxpand
Option ist jedoch tatsächlich für Bash 4.2 verfügbar. Ich habe dies mit einem Docker-Image in Version 4.2.53 durch Ausführen überprüftdocker run --rm bash:4.2 bash -c shopt | grep direxpand
(und zum guten Teil, dass es in Version 4.1.17 tatsächlich nicht durch Ausführen verfügbar istdocker run --rm bash:4.1 bash -c shopt | grep direxpand
).4.2.0
und bin auf die Tatsache gestoßen, dass es dort nicht funktioniert hat. Das Changelog erwähnt auch, dass es hinzugefügt wurdebash-4.3-alpha
. Ich nehme dann an, dass man überprüfen müsste${BASH_VERSINFO[2]}
, um genau zu sein, aber ich weiß nicht, welcher Punkt Release es hinzugefügt hat ...