OSに付属するシェルスクリプトを読んで技術を盗む
に触発されて比較的良く使うwhileコマンドを読んでみました。
分からないところもあったり、もしかしたら間違ってるところもあるかもしれないので、
気づいた方がいらっしゃったらコメント下さい。
while.sh
#! /bin/sh
# シェルのオプション設定
# ここでは e:コマンドが0意外のステータスで修了した場合、一部の場合を除いて即座に修了する
# f:パス名のワイルドカードによる展開を無効にする
set -ef
# kshのバージョンを確認
# シェルの種類によってputs関数の動作を定義してる
if test -n "$KSH_VERSION"; then
puts() {
print -r -- "$*"
}
else
puts() {
printf '%s\n' "$*"
}
fi
ALLMATCHES=0
# getoptsコマンドを使ってオプションの有無を確認
# オプションが指定されていた場合、$whichoptsにオプションが格納される
# 例えば[$ which -help]で実行された場合、$whichoptsにhelpが格納される
# $whichopts内に[a]が格納されていたらALLMATCHESを1にし、処理を継続
# 逆に、$whichopts内に[-a]以外のオプションが指定されている場合、?)の処理に移動する
while getopts a whichopts
do
case "$whichopts" in
a) ALLMATCHES=1 ;;
?) puts "Usage: $0 [-a] args"; exit 2 ;;
esac
done
# 不要になったオプション部分を切り捨てる
# また、exprコマンドの代わりに$((計算式))を使っている
shift $(($OPTIND - 1))
# 「$#」には引数の数が格納されている
# ここで、引数が一つも無ければ、変数ALLRETに1を格納する
if [ "$#" -eq 0 ]; then
ALLRET=1
else
ALLRET=0
fi
# 環境変数PATHを変数PATHに追加
# (*[!:]:)の処理ワカンネ('A`)
case $PATH in
(*[!:]:) PATH="$PATH:";;
esac
# 全引数を変数PROGRAMに格納し、for文を実行
for PROGRAM in "$@"; do
RET=1
# $IFSは区切り文字が格納されている。デフォルトはスペース
# ここで変数IFS_SAVEにスペースを格納し、
# IFS=:で新たに区切り文字を「:」に変更している
IFS_SAVE="$IFS"
IFS=:
case $PROGRAM in
# 引数の文字列内に「/」が入っていた場合の処理
*/*)
# $PROGRAMに格納されたファイルが存在し、実行可能であれば
# puts "$PROGRAM"を実行し、RETに0を代入
if [ -f "$PROGRAM" ] && [ -x "$PROGRAM" ]; then
puts "$PROGRAM"
RET=0
fi
;;
# 引数の文字列内に「/」以外が入っていた場合の処理
*)
# $PATHに格納された文字列を順に変数ELEMENTに格納
for ELEMENT in $PATH; do
# 変数ELEMENTが空であれば、変数ELEMENTに「.」を代入
if [ -z "$ELEMENT" ]; then
ELEMENT=.
fi
# $ELEMENT/$PROGRAMのパスで指定されたファイルが存在し、かつ実行可能であれば
# $ELEMENT/$PROGRAMを引数とし、puts関数を実行
if [ -f "$ELEMENT/$PROGRAM" ] && [ -x "$ELEMENT/$PROGRAM" ]; then
puts "$ELEMENT/$PROGRAM"
# 変数RETに0を代入
RET=0
# 変数ALLMATCHESが1かbreakでfor文終了
[ "$ALLMATCHES" -eq 1 ] || break
fi
done
;;
esac
# 区切り文字をスペースに戻す
IFS="$IFS_SAVE"
# 変数RETに代入された値が0でなければ、変数ALLRETに1を代入
if [ "$RET" -ne 0 ]; then
ALLRET=1
fi
done
exit "$ALLRET"