それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

bashでのif/while条件判断 に使える[[ / (( 条件の一覧<コマンド・ファイルの存在などで条件分岐>

bash ではいろいろな条件で分岐が出来る。

ifで使えるいろいろな条件を見てみたいと思う。

数値判断系

数字を比較するときは以下を覚えておけばいい。

(( 1 > 0  ))
(( 1 >= 0  ))
(( 1 < 0  ))
(( 1 <= 0  ))
(( 1 == 0  ))
(( 1 != 0  ))
((  0  )) # 終了ステータス 1 /if では false
(( 1  ))  # 終了ステータス0 /if ではtrue
((  ! 0  )) # 終了ステータス 0 /if では true
(( 1 && 1 ))
(( 0 ||1 ))

数値を比較するときは if (( 1!=0 )) ; then echo yes ; fi と書きます。この数値判断系の出来ることはlet と全く同じです。

(( ))のdouble parensis での記述方法は また別記事もっと詳細に書きます。

繰り返しになりますが (( もコマンドです。お忘れなきよう。

new スタイル test コマンド [[

test コマンド系です。

[[ -e /etc/pass ]]のようなダブルブラケット [[の記述は 新しいtest のスタイルです。

[[ が導入されたので、私も test も [ も使わず [[ で書くことが多い。

[[ による test コマンドは機能追加されている以外 [ と同等です。

そのため、紹介例も [[ で書きます。 [ / [[ / test の違いはまた別の記事に書きます。

繰り返しになりますが [[ もコマンドです。お忘れなきよう。

[[で導入された新しい書き方
[[ $name = takuya ]]     #  文字列マッチ 
[[ $name == takuya ]]   # 文字列マッチ
[[ $name == taku* ]]     # glob マッチ
[[ $name =~ ta.+ ]]       # 正規表現
[[ '' ]]       # 空文字は exit status 1 で if 中は false 扱い
[[ 'aaa' < 'aaaa' ]]    # 文字列の長さ比較
[[ 'aaa' > 'aaaa' ]]    # 文字列の長さ比較
[[ !$name =~ ta.+ ]]  # not による否定
[[ $var1 ||  $var2   ]]     #  ORによる条件
[[ $var1 && $var2 ]]     #  ANDによる条件
[[ で使える昔からの条件:ファイルチェック編
[[ -e <FILE> ]] #  パスが存在するか、存在したら true  / -a でも可だが、-a が AND と混同する恐れあり
[[ -f <FILE> ]] # パスが存在する and 通常ファイルであれば true
[[ -d <FILE> ]] # パスが存在する and ディレクトリであればtrue
[[ -c <FILE> ]] # パスが存在する and テキストファイルであれば true
[[ -b <FILE> ]] # パスが存在する and ブロックファイルであれば true
[[ -p <FILE> ]] # パスが存在する and 名前付きpipe であれば true
[[ -S <FILE> ]] # パスが存在する and ソケット であれば true
[[ -L <FILE> ]] # パスが存在する and Symlinkであれば true
[[ -h <FILE> ]] # パスが存在する and Symlinkであれば true
[[ -g <FILE> ]] # パスが存在する and sgid 付きであれば true
[[ -u <FILE> ]] # パスが存在する and suid 付きであれば true
[[ -r <FILE> ]] # パスが存在する and 読込可能であれば true
[[ -w <FILE> ]] # パスが存在する and 書込可能であれば true
[[ -x <FILE> ]] # パスが存在する and 実行可能であれば true
[[ -s <FILE> ]] # パスが存在する and サイズが0以上であれば true
[[ <FILE1> -nt <FILE2> ]]   # 最終更新日mtimeの比較。<FILE1> が <FILE2> より新しいとtrue
[[ <FILE1> -ot <FILE2> ]]   # 最終更新日mtimeの比較。<FILE1> が <FILE2> より古いとtrue
[[ <FILE1> -ef <FILE2> ]]   # <FILE1> と <FILE2> が同じinodeを指してたら true 
[[ -t <fd>     ]]     #   ファイルディスクリプタなら true
[[ / [ で使える昔からのtest条件:文字列
[[ -z $var ]] # 文字列が長さゼロ、つまり空文字 '' なら true
[[ -n $var ]] # 文字列が入っていたら true

ただし、これらは [[ を使う限りにおいて [[ !$var ]][[ $var ]] と同じなので明示する意図以外で使わないはず。

[[ / [ で使える昔からのtest条件:変数
[[ -v varname ]] # 変数が宣言されていたら true  / 配列の場合は array[n]
[[ -r varname ]] # 変数が未宣言なら true

コマンドの実行結果を判断に使う

繰り返しになりますが、if 文はコマンドの実行結果を使って判断しています。 コマンドの終了ステータスが 0 を見ています。

if command ;  then 
   do_something;
fi
複数行のコマンド実行結果

複数行のコマンドを併せて考えることが出来ます。

command && command 
command || command

if や while にかくと次のようにになります。

if command && command ; then ...
if command || command ; then ...
while command  && command ; do ...
複数コマンドを実行して最終実行で判断
command ; command ;
{ command ; command ; }
( command ; command  );

( ) はサブシェルを起動するので速度が遅いのと、変数空間が異なるので注意。

最後に。これら条件の確認方法。

while や if で使う条件のこれらの構文の動作チェックをしたいときは、次のようにチェックすると楽ですよ

[[ -e /etc/passwd ]];  echo $?

結果が 0なら、終了ステータス0なのでtrue になります。

これを幾つか組み合わせることで、bashの条件判断(と比較演算子)で何が起きているのか理解することが出来ます。

(( 0 )) ; echo $? #=> 1

また、別の記事書きますが、数字の比較と文字列の比較についてのよくあるミスも確認することも出来ます。

[[ 1000 < 11  ]] ; echo $?  #-> 0

この記事で紹介した条件は多岐にわたるので、自分のターミナルで試してみると安心して使えます。

参考資料