背景
makeがインストールされていない環境でmakeのようにターゲットを指定して処理を実行したいことがある。shellで引数にターゲットを指定して特定の処理のみを実行したり、複数のターゲットを連続で実行できるようにする。
環境
- Ubuntu 18.04.5
- dashまたはbash
実装
shell scriptの名前を build.sh
とする。
$ cat build.sh
# !/bin/sh
top_dir="$( cd "$( dirname "$0" )" >/dev/null 2>&1 && pwd )"
cd $top_dir
help()
{
echo "usage : $0 [target]..."
echo " all : execute all target"
echo " build : build"
echo " test : test"
echo " clean : clean"
echo ""
echo " help : show this message"
}
all()
{
build
}
build()
{
echo build
}
test()
{
echo test
}
clean()
{
echo clean
}
if [ "$#" = "0" ]; then
help
fi
for target in "$@" ; do
LANG=C type $target | grep function > /dev/null 2>&1
res=$?
if [ "x$res" = "x0" ]; then
$target
else
echo "$target is not a shell function"
exit $res
fi
done
解説
ディレクトリの移動
shell scriptが配置されているディレクトリに移動する。
# !/bin/sh
top_dir="$( cd "$( dirname "$0" )" >/dev/null 2>&1 && pwd )"
cd $top_dir
関数の実装
処理単位をshellの関数とする。
help()
{
echo "usage : $0 [target]..."
echo " all : execute all target"
echo " build : build"
echo " test : test"
echo " clean : clean"
echo ""
echo " help : show this message"
}
all()
{
build
}
build()
{
echo build
}
test()
{
echo test
}
clean()
{
echo clean
}
ヘルプ
引数が無いときはヘルプを表示する。
if [ "$#" = "0" ]; then
help
fi
ターゲットの呼び出し
for文で引数のターゲット毎に関数の有無をチェックする。
typeコマンドでコマンドがbuiltinコマンドなのか、shell関数なのかを判別する。
grepが文字列 "function" を検出したときは そのターゲットが関数と判断し、その関数を呼び出す。
for target in "$@" ; do
LANG=C type $target | grep function > /dev/null 2>&1
res=$?
if [ "x$res" = "x0" ]; then
$target
else
echo "$target is not a shell function"
exit $res
fi
done
使用例
引数なし
ヘルプメッセージが表示される。
$ sh build.sh
usage : build.sh [target]...
all : execute all target
build : build
test : test
clean : clean
help : show this message
Build
$ sh build.sh build
build
$ sh build.sh clean
clean
$ sh build.sh test
test
連続実行
複数のターゲットを順に実行する。
$ sh build.sh all clean test
build
clean
test
エラー
不正なターゲットの場合は停止する。
$ sh build.sh all hoge test
build
hoge is not a shell function