私は、異なるHPCノード、仮想マシン、またはプライベートワークステーションで異なるバージョンのBashを実行できる比較的異質な環境で働いています。ログインスクリプトをGitリポジトリに入れたので、.bashrc
「このホストなら...」と同じタイプの混乱なしに、全体的に同じスクリプトを使用したかったのです。
私良いBash 4.1 以下の基本動作は、キーを押したときの動作cd $SOMEPATH
に拡張されました。 Bash 4.2以降では、この動作を再度有効にする必要があります。cd /the/actual/path
Tabshopt -s direxpand
それない2029年2月4日まで。ただし、これは単なる例であり、関連性がある可能性がある別のshopt
オプションcomplete_fullquote
です。正確にその効果)はv4.2のデフォルト動作を変更することもできます。
ただし、direxpand
以前のバージョンのBashは認識されず、私がshopt -s direxpand
これを試みると、.bashrc
以前のバージョンのBashを使用してノードにログインするたびにコンソールにエラーメッセージが表示されます。
-bash: shopt: direxpand: invalid shell option name
私がしたいのは、shop -s direxpand
以前のバージョンのBashに影響を与えずに、強力な方法でBash> 4.1でオプションを有効にする条件をラップすることです(つまり、エラー出力を)にリダイレクトするわけではありません/dev/null
。
答え1
エラーにリダイレクトするのは理解できません/dev/null
。コードを強力にするには、set -e
次の一般的なイディオムを使用してください… || true
。
shopt -s direxpand 2>/dev/null || true
オプションがない場合にいくつかの代替コードを実行するには、次の戻り状態を使用してくださいshopt
。
if shopt -s direxpand 2>/dev/null; then
… # the direxpand option exists
else
… # the direxpand option does not exist
fi
ただし、リダイレクトエラーが本当に気に入らない場合は、完了メカニズムを使用してセルフチェックを実行できます。これはbash 2.03以下で、プログラム可能な完了機能を持たない古いシステムがないと仮定します。
shopt_exists () {
compgen -A shopt -X \!"$1" "$1" >/dev/null
}
if shopt_exists direxpand; then
shopt -s direxpand
fi
この方法は、一部の環境(Cygwinなど)で遅い分岐を防ぎます。シンプルなので2>/dev/null
性能面では勝てないと思います。
答え2
direxpand
出力に存在することを確認し、shopt
存在する場合はアクティブにします。
shopt | grep -q '^direxpand\b' && shopt -s direxpand
答え3
特定の人を識別するときshopt
オプションBashの一部のメジャー/マイナー/パッチバージョンで使用でき、$BASH_VERSION
変数または配列の要素を確認して条件付きで$BASH_VERSINFO[]
アクティブにすることができます。
これはBash 4.2.29以降のテストです。direxpand
初めて紹介された4.2シリーズの場合:
if [[ $BASH_VERSION == 4.2.* && ${BASH_VERSINFO[2]} -ge 29 ]] ||
[[ ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -ge 3 ]] ||
[[ ${BASH_VERSINFO[0]} -ge 5 ]]; then
shopt -s direxpand
fi
編集する:明らかに、これはログインスクリプトのエラーメッセージを単に無視するための過度のエンジニアリングソリューションですが、とにかく私の参照のために記録したいと思いました。
周囲の中括弧に注意してください。${BASH_VERSINFO[index]}
はい(ロケールによる)語彙比較の代わりに整数を実行するためのandの-eq
使用も必要です。-gt
引用しない場合、演算子のRHSは、前述のように、Bash /条件で「extglob」パターン==
として扱われます。[[
]]
ここ、これは正規表現IMOよりも美しい「スタート」比較を提供します。
これ$BASH_VERSINFO
大量に次の出力に表示されるすべての情報が含まれていますbash --version
。
bash --version | head -1
# result:
# GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
declare -p BASH_VERSINFO
# result:
# declare -ar BASH_VERSINFO='([0]="4" [1]="3" [2]="48" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu")'
いついいえshopt
Lucianoが提案したアプローチが良いというBashバージョンがサポートされているか、動作が変更された文書で明らかです。
# note the '-q' so that the matched pattern isn't actually printed
shopt | grep -q direxpand && shopt -s direxpand
...Gillesが提案した解決策のように、エラー()を無視して必要があることをshopt -s direxpand 2>/dev/null
確認してください。$?
引用:1、2、サム
関連読書:スーツと買い物、なぜ二人ですか?