bashの";", "&&", "||" に関する補足ネタ。コマンドグルーピングとの併用例

  • 22
    Like
  • 0
    Comment
More than 1 year has passed since last update.

複数のターミナルコマンドを順番に実行する時につける「&&」と「;」と「||」の違い - Macの手書き説明書

「;」は他のコマンドの実行結果に依存せず順番に実行される

のですが、具体的にどういう場面で;を使うかというと、{}( もしくは() )を使ったグルーピングと併用するケース が経験上多いような気がします。

{CMD1; CMD2; CMDn; }

例えばこんなケースです。

$ { echo "hoge"; echo "huga"; } > x.log

このコマンドを実行すると、x.logには

hoge
huga

それぞれのコマンドの実行結果が リダイレクト出力されます。

これを単に

$ echo "hoge"; echo "huga" > x.log

とすると、hogeは標準出力に出力されてhugaだけがx.logに出力されます。

(CMD1; CMD2; CMDn)

()でも同様にグルーピングが可能ですが、{}との違いは

  • 最後のコマンドの後ろには;(とスペース)は不要です
  • ()サブシェルで(別プロセスで) 動きます

どういった挙動の差異が生まれるかは↓の例が分かりやすいと思います。

$ pwd
dirParent

$ mkdir dirX
$ touch dirX/fileX

# {} の場合
$ {cd dirX; ls; } > hoge.log
$ pwd
dirParent/dirX  # dirXにcdしている
$ cat ../hoge.log
fileX

# () の場合
$ (cd dirX; ls) > huga.log
$ pwd
dirParent # dirXにcdしない(サブシェル内ではcdしてるけど完了後に元のシェルに戻る)
$ cat huga.log
fileX

三項演算子

引用元記事では&&||についても言及がありましたが、これと;を使ったグルーピングを併用すると、

[[ CONDITION ]] && { CMD1; CMDn; } || { CMDe1; CMDen; }

↑三項演算子はこう書けます。
CONDIONが真の場合は&&後のコマンド群が、偽の場合は||後のコマンド群が実行されます。
シェルスクリプトなんかで条件判定が偽の場合にexitしたい、ってケースなんかは

[[ CONDITION ]] && { CMD1; CMDn; } || { CMDe1; CMDen; exit; }

こう書くと良いでしょう。

ちなみにこれもサブシェル()によるグルーピングで書けますが、 上記のexitしたいケースで()を使った場合、「サブシェルをexitする」事になるので、元のスクリプト自体はexitせず処理が継続します 。ってのが注意点。

なおbashなので可読性云々についてはry