複数のターミナルコマンドを順番に実行する時につける「&&」と「;」と「||」の違い - 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