LoginSignup
5
5

More than 5 years have passed since last update.

whileコマンドを読んでみた

Posted at

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"
5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5