Skip to main content

if と test コマンドについて

前提知識

概要

  • if は、コマンド実行結果(return code) が 0 かそうでないかだけを見ている
  • それに倣って各コマンドは慣例的に return code に 正常: 0、異常: 非0 (通常1、区別したい場合は2以降) を返す
  • [ .. ] も実はただのコマンドで、中に記載した条件が 真なら 0、偽なら 1 を返す
  • 直前のコマンドの return code を確認したい場合は $? で確認可能
    • 例えば デバッグ目的で echo したあとは $? に入るのは echo の結果(通常0) なので注意
  • ! は、結果を反転するコマンド(シェル演算子)

ということから、

  • if に渡すもの自体は [ .. ] である必要はなく、コマンド自体の return code を使いたい場合は囲わずに直接書く

例1: return code 確認

bash
ls /no/such/file 2> /dev/null
echo $? # => 1 と出る
echo $? # => 0 と出る (1個前の echo コマンドは成功しているから)

例2. test コマンド if [ .. ] での判定

bash
if [ "$x" = "" ]; then
echo "x is empty"
fi

例3. コマンド実行自体 if <command> での判定

bash
if ! ls /no/such/file 2> /dev/null; then
echo "file not found"
fi

例4. コマンド実行直後、 $? で判定

bash
ls /no/such/file
if [ $? -ne 0 ]; then
echo "file not found"
fi

デバッグ目的で echo するとハマるので注意

bash
ls /no/such/file
echo $? # => 1 と出るが、コマンド結果は 0
if [ $? -ne 0 ]; then
echo "file not found" # 一生通らなくなってしまう
fi

その場合は、面倒でも変数に入れる

bash
ls /no/such/file
r=$?
echo $r # => 1
if [ $r -ne 0 ]; then
echo "file not found"
fi

test コマンドの演算子について

論理演算子系

演算子逆向き意味
=!=文字列の 一致/不一致
\>\<文字列の より大/より小 (辞書順) ← 「以上/以下」は存在しない
-eq-ne数値の 一致/不一致
-gt-lt数値の より大/より小
-ge-le数値の 以上/以下
-z-nカラ文字かどうか (= "" でも同じ)
!否定
if [ "$x" = "abc" ]; then
echo "ok"
fi

ファイル系

演算子意味
-f通常ファイルかかどうか
-dディレクトリかどうか
-Lシンボリックリンクかどうか
-eファイル/ディレクトリ 等の区別なく、存在チェック
-r権限: 読み取り可能 (read)
-w権限: 書き込み可能 (write)
-x権限: 実行可能 (execute)
if [ ! -f "a.txt" ]; then
echo "not found"
fi

二重のカッコ [[ .. ]] について

  • [[ .. ]] は Bash 固有の機能(というより ksh から取り込まれた拡張)で、条件に使える文がちょっと便利になる
#やりたいこと[ .. ][[ .. ]][[ .. ]] で うれしいこと
1文字列の一致など[ "$x" = "abc" ][[ $x = "abc" ]]クォートなくても事故りづらい (カラ文字のケースなど)
2正規表現での一致[ `echo "$x" | grep -c "^abc"` -gt 0 ][[ $x =~ ^abc.* ]]構文として存在する
3glob での一致なし[[ $x == abc* ]]構文として存在する
4and[ .. ] && [ .. ][[ .. && .. ]]どちらでも良いな
5or[ .. ] || [ .. ][[ .. || .. ]]どちらでも良いな
6文字列の大小\\>, \\<>, <エスケープが不要

※ 2 の [ 版の例については、grep -q (結果を return code で判別) とするほうが良いが、[ を使う例として、無理やりこうした

and, or について補足

昔ながらの書き方 (POSIX準拠という)

bash
if [ "$x" -eq 0 ] && [ "$y" -eq 0 ]; then

Bash 前提の書き方でも良いなら

bash
if [[ $x -eq 0 && $y -eq 0 ]]; then

以下広告