dateコマンドがGNU dateなのかBSD dateなのか見分ける方法です。
結論
date -d 0hour > /dev/null 2>&1 && echo "GNU date" || echo "BSD date"
※ 10/19追記: --version
でも同じ結果が得られます。GNU dateには --version
がありますが、BSD dateにはありません。
Linux系OS(Ubuntu)での実行結果
date -d 0hour > /dev/null 2>&1 && echo "GNU date" || echo "BSD date"
#=> GNU date
BSD系OS(macOS)での実行結果
date -d 0hour > /dev/null 2>&1 && echo "GNU date" || echo "BSD date"
#=> BSD date
※ シェルがcsh系だと Ambiguous output redirect.
となります。
条件判定を逆(True側に BSD date を持ってきたい)場合
date -v+0H > /dev/null 2>&1 && echo "BSD date" || echo "GNU date"
どういうことだってばよ
dateコマンドは、主にLinuxで動く GNU date と、主にmacOSで動く BSD date でオプションが異なります。
特にLinuxとmacOSでは共にBashが動くこともあり、書いたBashスクリプトの99.9%は共通なのに、dateコマンドのせいでションボリというわけです。
※ "date コマンドつらい" なんて話もありますね。
※ top(1) も似たような話がありますね。
そのための判定基準を探したというのが経緯です。
それぞれのdateの違い
最大の違いは、"今から2時間後" といった相対日時算出のオプションがあります。
GNU date は -d
(--date
) で、BSD date は -v
で相対日時を算出します。
また、それぞれに対応するオプションが存在しないので、必ずどちらかで失敗するのを利用して見分けています。
実際にやるとしたら
date コマンドの実行結果 $?
を見て分岐することになるでしょう。
下の例では変数に入れてますが、一回しか使わないのであれば $?
の直接参照でも良さそうです。
date -d 0hour > /dev/null 2>&1 # inspect
readonly _IS_DATECMD=$([[ "$?" -eq 0 ]] && echo "GNU" || echo "BSD") # judge (likes ternary operator)
echo $_IS_DATECMD
if [ "$_IS_DATECMD" == "GNU" ]; then
TWO_HOUR_AGO=$(date --date "2 hours ago") # GNU date option
else
TWO_HOUR_AGO=$(date -v-2H) # BSD date option
fi
echo $TWO_HOUR_AGO
あとがき
さて、私が見分けられるかな…?! (お疲れ
「dateコマンドつらい」ブログは、同僚エンジニアのブログでした。めちゃんこ役立ちました!!あざます ogu++ !!
EoT