Syntax Error.

[Sy] シェルスクリプトのif文の条件式で「command not found」となるやりがちなミスに気をつけよう

2016/07/11

シェルスクリプトでif文の条件式などに使うif [・・・]; thenという構文ですが、あることに気をつけないとcommand not foundと怒られます。

たまにシェルスクリプトを書くとついつい同じミスをやってしまいます。

if文の条件式で command not found となってしまう

例えば、引数を一つ受け取ってその引数がabcと一致するかどうか判定して、一致したらtrue、一致しなかったらfalseと出力するだけの単純なtest.shというシェルスクリプトを考えます。

[test.sh]

# !/bin/sh

if [$1 = "abc"]; then
  echo "true"
else
  echo "false"
fi

一見特に問題なさそうですが、この状態で実行すると、

$ ./test.sh abc
./test.sh: line 3: [abc: command not found
false

となります。

何がいけないのか?

答えを先に言っちゃうと、if文の条件式のところはこう書かないといけません。

[test.sh]

# !/bin/sh

if [ $1 = "abc" ]; then
  echo "true"
else
  echo "false"
fi

これでエラーが起きなくなります。

$ ./test.sh abc
true

$ ./test.sh abd
false

修正したのは、[$1 = "abc"]となっていた部分を[ $1 = "abc" ]と、スペースを入れてあげただけです。

実はシェルスクリプトのif文などで使われる[・・・];という部分は、 testコマンド というコマンドのもう一つの記述方法なんです。

どういうことかというと、先ほどのスクリプトは以下のように書き換えることができます。

[test.sh]

# !/bin/sh

if test $1 = "abc"; then
  echo "true"
else
  echo "false"
fi

testコマンドは条件式の判定を行い、trueかfalseを返す ので、if文などの構文で使われます。ただ、上のようにif test $1 = "abc"と書くとちょっと見づらいですよね?

なので[という別の記述もできるようになっていて、[でtestコマンドを書いた場合は条件式の最後に]をつけて閉じてあげる必要があります。

最初のエラーは、[というコマンドとして処理しないといけないのに、変数$1の前にスペースを入れていなかったので、 [$1というコマンドとして認識されてしまい、そんなコマンドはないよ!と怒られちゃったわけですね。

PHPやJavaScriptのような一般的なスクリプト言語では条件式を()で囲みますが、(の後ろと)の前にスペースがあってもなくても当然問題ありません。

そのノリでシェルスクリプトを書くと、このエラーが出るので注意しましょー。