Q1[ -f config.txt ]は何を判定しますか?
条件分岐 — if と [ ] でファイル・数値を判定
この記事は、基礎コマンドからシェルスクリプトまでLinuxの実践的なスキルを1からマスターする「Linux入門講座の一部」です。
[ -f config.txt ]や[ -z "$name" ]・[ "$count" -lt 5 ]でファイル・文字列・数値を判定し、if/elif/elseで処理を分け、caseで複数パターンを振り分ける方法を、図解とブラウザ端末で書いて実行します。
値を比べて分岐する — 文字列比較と数値比較
シェルスクリプトでは、文字列が一致するか・数値が大きいかを調べて処理を変えます。
判定にはtestコマンド、または同じ働きの[ ... ]を使います。
[と]の内側は前後に空白が必要で、[ "$count" -lt 5 ]のように書きます。
判定が真なら終了コード 0、偽なら 1 を返します。
文字列の比較は=(一致)・!=(不一致)、空かどうかは-z(空)・-n(非空)で調べます。
数値の比較は-eq(等しい)・-ne(等しくない)・-lt(より小さい)・-gt(より大きい)を使い、文字列と数値で演算子が違う点に注意します。
変数は[ -z "$name" ]のように二重引用符で囲むと、空でも構文が崩れず安全です。
count=3
mode="dev"
[ "$count" -lt 5 ] && echo small # 3 は 5 未満なので small
[ "$count" -gt 0 ] && echo positive # 0 より大きいので positive
[ "$mode" = "prod" ] || echo other # prod ではないので other
[ -z "$mode" ] || echo has-mode # 空ではないので has-mode
[ ... ]は真なら終了コード 0、偽なら 1 を返し、ifが真でthen、偽でelseに進みます。| 書き方 | 意味 | 例 |
|---|---|---|
[ "$a" = "$b" ] | 文字列 a と b が一致すれば真 | [ "$mode" = "prod" ] |
[ "$a" != "$b" ] | 文字列 a と b が異なれば真 | [ "$mode" != "dev" ] |
[ -z "$v" ] | 変数 v が空なら真 | [ -z "$name" ] && echo empty |
[ -n "$v" ] | 変数 v が空でなければ真 | [ -n "$name" ] && echo set |
[ "$a" -eq N ] | 数値 a が N と等しければ真 | [ "$count" -eq 0 ] |
[ "$a" -ne N ] | 数値 a が N と異なれば真 | [ "$count" -ne 0 ] |
[ "$a" -lt N ] | 数値 a が N より小さければ真 | [ "$count" -lt 10 ] |
[ "$a" -gt N ] | 数値 a が N より大きければ真 | [ "$count" -gt 0 ] |
ファイルやフォルダを調べる — -f / -d
スクリプトでは、設定ファイルがあるか・出力先のフォルダができているかを確認してから処理を進めます。
ファイルの有無は-f(通常ファイルが存在)、フォルダの有無は-d(ディレクトリが存在)で判定します。
種類を問わず存在だけを確認したいときは-e、中身が空でないかは-sを使います。
判定の書き方は文字列・数値のときと同じ[ ... ]で、[ -f config.txt ]のようにパスを渡します。
真なら終了コード 0、偽なら 1 を返すので、ifや&& / ||と組み合わせてあれば使う・なければ作るという初期化処理を書けます。
touch report.txt # 素材を作成
[ -f report.txt ] && echo exists # ファイルがあるので exists
[ -d report.txt ] || echo notdir # ディレクトリではないので notdir
mkdir logs # フォルダを作成
[ -d logs ] && echo hasdir # ディレクトリがあるので hasdir
-fは通常ファイル、-dはディレクトリ、-eは種類を問わず存在を判定します。同じパスでも調べる観点で結果が変わります。| 書き方 | 意味 | 例 |
|---|---|---|
[ -f f ] | f が通常ファイルとして存在すれば真 | [ -f config.txt ] && echo found |
[ -d d ] | d がディレクトリとして存在すれば真 | [ -d logs ] && echo dir |
[ -e p ] | p が種類を問わず存在すれば真 | [ -e data ] && echo there |
[ -s f ] | f が存在し中身が空でなければ真 | [ -s log.txt ] && echo nonempty |
処理を分ける — if / elif / else
ifは条件が真のときだけthenの処理を実行します。
複数の条件を順に試すときはelif、どれにも当てはまらないときはelseを続け、fiで閉じます。
if 条件; then 処理; fiのようにセミコロンで区切るか、行を分けて書きます。
count=3
if [ "$count" -eq 0 ]; then
echo "none"
elif [ "$count" -lt 5 ]; then
echo "few ($count)"
else
echo "many ($count)"
fi # few (3) と表示される
ifから順に条件を試し、最初に真になった枝の処理だけを実行します。どれも偽ならelseに進みます。| 書き方 | 意味 | 例 |
|---|---|---|
if 条件; then … fi | 条件が真のとき処理する | if [ -f f ]; then echo ok; fi |
then | 条件が真のとき本体を開始 | if [ -f f ]; then echo ok; fi |
elif 条件; then … | 前の条件が偽で次を試す | elif [ "$n" -lt 5 ]; then … |
else … | どれも偽のとき処理する | else echo other; fi |
fi | if を閉じる | if …; then …; fi |
複数パターンを振り分ける — case
1 つの値を多くの候補と照合するときはcaseが読みやすく書けます。
case 値 in パターン) 処理 ;; esacの形で、各パターンの末尾に;;を置き、*)でどれにも一致しない場合を受けます。
ifを何段も重ねるより分岐の意図が明確になります。
action="start"
case "$action" in
start) echo "starting service" ;;
stop) echo "stopping service" ;;
*) echo "unknown action: $action" ;;
esac # starting service と表示される
caseは値を上からパターンに照合し、最初に一致した枝だけを実行してesacで閉じます。*)はどれにも一致しない場合です。| 書き方 | 意味 | 例 |
|---|---|---|
case x in pat) … ;; esac | 値を複数パターンに振り分ける | case "$1" in start) … ;; esac |
pat) | 値と照合するパターン | start) echo go ;; |
;; | case の各処理の終わり | start) echo go ;; |
*) | どれにも一致しない場合 | *) echo other ;; |
esac | case を閉じる | case x in …; esac |
理解度チェック
まずは1問ずつ答えてみましょう。
Q2前の条件が偽だったときに別の条件を続けて試すキーワードはどれですか?
Q3caseで各パターンの処理の終わりに置く記号はどれですか?