シェル内で使うフラグのイディオム

今まで if test "$is_darwin" == "true" のようにやっていたが、これは冗長だろう。alias を使う方法も考えたが、こと真偽値で判定する場合についてはリターンコード(エラーコード)がそのまま使えるのだから、以下のような書き方が、最も汎用性があり、なおかつ簡潔だろう。

#!/bin/sh

is_darwin() { test "$(uname)" == "Darwin"; }
is_linux()  { test "$(uname)" == "Linux"; }

if is_darwin
then
  echo "This is Darwin."
else
  echo "This is not Darwin."
fi

if ! is_linux
then
  echo "This is not Linux."
else
  echo "This is Linux."
fi

判定は動的ですし。

#!/bin/sh
# -*- coding: utf-8 -*-

at_home() { test "$PWD" == "$HOME"; }

cd /
if at_home
then
  echo "Here $PWD, I'm at home."
else
  echo "Here $PWD, I'm out of home."
fi

cd
if at_home
then
  echo "Here $PWD, I'm at home."
else
  echo "Here $PWD, I'm out of home."
fi

あとは predicate のネーミングルールかな。Ruby のように識別子に ? が使えるとカッコいいのだが、そうも行かない。Lisp 畑の人であれば、postfix に p かな。

darwinp() { test "$(uname)" == "Darwin"; }
linuxp()  { test "$(uname)" == "Linux"; }

if darwinp || linuxp
then
  echo "This is a *NIX environment."
fi

いや、若干 snob で、いやらしいかな?

Note: 問題があるとすれば、Bash では、変数がローカルのダイナミックスコープを持てるのと違って、関数にはスコープがグローバルスコープしかないので、関数内にローカルな関数が定義できないことですね。

Note: いや、そんなことはないですね。bash(1) を見ると、関数にする “Compound Commands” は同じプロセス環境で動く { ... } ではなく、サブシェルを起動する ( ... ) でも良いということなので、新規プロセス起動のオーバーヘッドが問題にならないのであれば、子プロセス内でローカル関数を定義すれば、より構造化されたシェルスクリプトが書ける。