はじめに
「アタイも挑戦したい、管理人みたいに」1、nikkieです。
シェルスクリプトを書いたり読んだりする中でif
文の条件に使う[
が1つだったり2つだったり、違いがよく分からないなと感じていました。
『マスタリングLinuxシェルスクリプト 第2版』にあたって深まった理解を、[
が分からない過去の私向けにアウトプットします。
目次
- はじめに
- 目次
- まとめ:現時点のtestと[と[[の理解
- 動作環境
- testと[と[[
- 例で見るtestと[と[[
- もう一例:複数の条件の場合
- IMO:testと[と[[の使い分け
- 終わりに
- 参考文献
まとめ:現時点のtest
と[
と[[
の理解
シェルスクリプトに関しては伸びしろ豊富と思いますので、フィードバック大歓迎です。
test
と[
は同じ(違いはない)[
はtest
の省略表記
[[
はtest
や[
より高機能
動作環境
macOS 12.6のPC(zshがデフォルト)で、bashを立ち上げて動作確認しました。
% bash $
test
と[
と[[
test
シェルの組み込みコマンドです。
$ type test test is a shell builtin $ which test /bin/test
test -e
はファイルが存在するかをテストします。
- 存在していたら終了コードは0
- 存在していなければ終了コードは1
$ touch awesome.txt $ test -e awesome.txt ; echo $? 0 $ rm awesome.txt $ test -e awesome.txt ; echo $? 1
オンラインで読めるマニュアルはこちら2
[
シェルの組み込みコマンドです。
(ちょ、おま、コマンドだったの!?)
$ type [ [ is a shell builtin $ which [ /bin/[
[
はtest
コマンドの省略版です。
man test
より
test, [ – condition evaluation utility
test
と[
は同じ!
先ほどの例を書き換えてみましょう。
$ touch awesome.txt $ [ -e awesome.txt ] ; echo $? 0 $ rm awesome.txt $ [ -e awesome.txt ] ; echo $? 1
[[
キーワードです。
キーワードには他にif
などがあります。
$ type [[ [[ is a shell keyword $ type if if is a shell keyword
test
や[
の例は[[
を使っても書き換えられました。
$ touch awesome.txt $ [[ -e awesome.txt ]] ; echo $? 0 $ rm awesome.txt $ [[ -e awesome.txt ]] ; echo $? 1
test
や[
との違いは「高度な条件テスト」ができることだそうです(『マスタリングLinuxシェルスクリプト 第2版』 5.4)。
この記事では立ち入りませんが、パターンマッチングや正規表現を使った条件テストが紹介されていました。
例で見るtest
と[
と[[
ここまでに確認した例をスクリプトにまとめました3。
test
の例も[
の例も[[
の例も、書き方は異なりますが動作としては同じです。
$ touch awesome.txt $ ./test_and_brackets_single.sh awesome.txtあり awesome.txtあり awesome.txtあり $ rm awesome.txt $ ./test_and_brackets_single.sh awesome.txtなし awesome.txtなし awesome.txtなし
もう一例:複数の条件の場合
if
文の条件が複数ある場合、test
や[
と、[[
の間で違いがありました。
test
や[
は2つの書き方ができます:
[[
は複数のオプションを&&
や||
でつなぐのみです。
(-a
でつないでみたら「syntax error in conditional expression」と表示され、できないってことかなと認識しました5)
複数の条件のスクリプト例はこちらです:
$ touch awesome.txt $ ./other_example.sh awesome.txtがあって読める awesome.txtがあって読める awesome.txtがあって読める $ rm awesome.txt $ ./other_example.sh awesome.txtがないか読めない awesome.txtがないか読めない awesome.txtがないか読めない
IMO:test
と[
と[[
の使い分け
test
と[
が同じ意味と理解しました。
この2つであれば打鍵数が少ない[
を使いたいかなという気持ちです。
[
はコマンドと知られたのが大きいなと感じています。
[[
ですが、test
や[
と同じことができ、[[
にしかできないこと(パターンマッチや正規表現)もあるという理解です。
[[
と[
は複数の条件のつなぎ方が異なるので、[[
がどうしても必要でない限りは[
を使いたいなと思いました。
[[
と[
を併用すると、慣れていないがゆえに混乱しそうなのですが、[
に統一することでそれを避けられそうと考えています。
終わりに
test
と[
と[[
、完全に理解した!
同じ部分・違う部分が分かったことで、使い分けの指針(暫定版)もできました。
シェルスクリプトでif
文を書くときに[
の数に迷わずに書いていけそうです!
参考文献
1章
3章
5章
- 5.1 testコマンドの要約
- 5.4 [[を使った高度なテスト
- https://youtu.be/P5LLhoKfI1E?t=36↩
- 「この文書はもうメンテナンスされていない」とありますが、Man page of TESTは、オプションを日本語でざっと知る助けになりました↩
-
if
文の条件の評価はセミコロンを入れて1行にする書き方とセミコロンは入れずに改行してthen
を続く行にする書き方があることを知り(ref: 3.4)、このスクリプトで試しています↩ -
ShellCheckによると、複数の
test
コマンドをコマンドラインリストでつなぐ方が好ましいようです。ref: ShellCheck: SC2166 – Prefer `[ p ] && [ q ]` as `[ p -a q ]` is not well defined.↩ -
ShellCheckによると
[[
の中では-a
の代わりに(instead of)&&
を使うべきなようです。ref: ShellCheck: SC2108 – In `[[..]]`, use `&&` instead of `-a`.↩