【Shell Script】test・[ ]・の違いと比較演算子

Shell Script

こんにちは、かつコーチです。

前回は、if文の基本形と、数値比較・文字列比較の演算子の違いを解説しました。

条件式の中でさらっと使っていた[ ]ですが、実はtestコマンドや[[ ]]という仲間があり、それぞれ挙動が微妙に異なります。

「なぜ現場のスクリプトには[[ ]]を使うものと[ ]を使うものが混在しているのか」と疑問に思った方もいるはずです。

今回は、この3つの違いを比較しながら、どれを選ぶべきかの判断軸を明確にしていきます。

test・[ ]・とは?

条件を判定する3つの道具

testとは、条件が真か偽かを判定するコマンドの名前そのものです。

[ ]は、このtestコマンドの別名(エイリアス)として用意された、より簡潔に書ける記法です。

[[ ]]は、bash独自に拡張された、より高機能で安全な条件判定の構文です。

判定する道具という意味では3つとも同じ役割ですが、精度や機能が異なる「進化した物差し」だとイメージすると分かりやすいです。

昔ながらの目盛りだけの物差し(test[ ])と、誤差を自動補正してくれる高精度な物差し([[ ]])の違いに近いものがあります。

なぜ違いを知る必要があるのか

[ ]は歴史的な経緯から他のシェル(shなど)との互換性を保つために存在し、[[ ]]はbashやzshなど一部のシェルでしか使えません。

互換性を優先するスクリプトでは[ ]が、bash専用と割り切れるスクリプトでは[[ ]]が向いているというように、目的によって使い分けが必要になります。

3つの記法の比較

基本構文の違い

まずは同じ条件を、3つの書き方で比較してみます。

#!/bin/bash
count=10

# testコマンド
if test "$count" -gt 5; then
  echo "testで判定:5より大きい"
fi

# [ ](testのエイリアス)
if [ "$count" -gt 5 ]; then
  echo "[ ]で判定:5より大きい"
fi

# [[ ]](bash拡張構文)
if [[ $count -gt 5 ]]; then
  echo "[[ ]]で判定:5より大きい"
fi

3つとも同じ結果になりますが、[[ ]]だけは変数をダブルクォートで囲まなくても、単語分割によるエラーが起きにくいという違いがあります。

比較表:test / [ ] /

項目test[ ]
正体単独のコマンドtestのエイリアスbash拡張の構文(予約語)
対応シェルsh・bash・zsh等広く対応sh・bash・zsh等広く対応bash・zsh等一部のみ
変数のクォート必須(省略すると事故の元)必須(省略すると事故の元)省略しても比較的安全
論理演算子-a -o(非推奨)-a -o(非推奨)&& `
パターンマッチ不可不可==でワイルドカード可
主な用途互換性重視のスクリプト昔ながらのシェルスクリプトbash専用の現代的なスクリプト

互換性が求められる環境(/bin/shで動かす前提のシステムスクリプトなど)では[ ]、それ以外の通常のbashスクリプトでは[[ ]]を選ぶのが現場での一般的な判断軸です。

どちらを選べばいいか:判断フロー

  • 対象OSやDockerイメージがsh(dashなど)で動く可能性がある → [ ]を使う
  • Ubuntu 26.04 LTSのbash前提で、自分(またはチーム)だけが使うスクリプト → [[ ]]を使う
  • 迷ったら、まずは[[ ]]を使い、互換性の指摘を受けたら[ ]に置き換える

比較演算子の一覧

数値比較演算子

演算子意味
-eq等しい[ "$a" -eq "$b" ]
-ne等しくない[ "$a" -ne "$b" ]
-gtより大きい[ "$a" -gt "$b" ]
-ge以上[ "$a" -ge "$b" ]
-ltより小さい[ "$a" -lt "$b" ]
-le以下[ "$a" -le "$b" ]

文字列比較演算子

演算子意味
=等しい[ "$a" = "$b" ]
!=等しくない[ "$a" != "$b" ]
-z空文字である[ -z "$a" ]
-n空文字でない[ -n "$a" ]

[[ ]]の中では、==を使うとワイルドカードによるパターンマッチも可能になります。

filename="report.txt"
if [[ $filename == *.txt ]]; then
  echo "txtファイルです"
fi

よくあるつまずきポイント:スペースの数え間違い

私が新人時代、[ ]の中のスペースを詰めて書いてしまい、原因が分からず1時間近く悩んだことがあります。

❌ Before:かっこと条件式の間にスペースがない

count=10
if [$count -gt 5]; then
  echo "5より大きい"
fi
bash: [10: command not found

[testコマンドの別名であり、コマンドである以上、引数との間には必ずスペースが必要です。

[$countのようにくっつけて書くと、シェルは[10という1つの(存在しない)コマンド名として解釈してしまいます。

✅ After:かっこと条件式の間に必ずスペースを入れる

count=10
if [ "$count" -gt 5 ]; then
  echo "5より大きい"
fi

[の後ろと]の前、両方にスペースが必要です。

このルールを知らないと「unary operator expected(単項演算子が期待されている)」といった別のエラーに遭遇することもあるので、[ ]を書くときは常にスペースの有無を意識してください。

応用・一歩先の使い方

ファイル判定オプションとの組み合わせ

test[ ][[ ]]はいずれも、ファイルの種類を判定するオプションと組み合わせて使えます。

if [[ -d "/var/backup" ]]; then
  echo "ディレクトリが存在します"
fi

if [[ -x "/usr/bin/bash" ]]; then
  echo "実行可能なファイルです"
fi

-dはディレクトリ判定、-xは実行権限の有無を判定するオプションで、SH02で扱った実行権限の確認にも応用できます。

まとめ

この記事のポイント

  • test[ ][[ ]]は判定の役割は同じだが、対応範囲や安全性が異なる
  • 互換性重視なら[ ]、bash専用の現代的なスクリプトなら[[ ]]を選ぶ
  • [はコマンドの別名なので、前後に必ずスペースを入れる
  • 数値比較は-eq系、文字列比較は=系の演算子を使う

次に読むべき記事

次回は、条件分岐と並んでよく使う繰り返し処理として、for文・whileループの書き方を解説します。

→ 次の記事:for文・whileループで繰り返し処理をする

タグ: Shell, 中級者向け, 制御構文

タイトルとURLをコピーしました