Bashのスクリプトをshで実行するとsh互換のBashとして動作した

Tech

先日仕事でシェルスクリプトを書いていたのですが、想定しないsyntaxerrorが出て、かなり詰まったことがあったのでメモがてら残しておきます。

事象と解決策

詰まったスクリプトは次のようなものでした。

#!/bin/bash
diff <(echo aaa) <(echo bbb)

これを次のように実行するとエラーになります。

$ sh difftest.sh
difftest.sh: line 3: syntax error near unexpected token `('
difftest.sh: line 3: `diff <(echo aaa) <(echo bbb)'

これの解決策が分からず、数時間を無駄にしてしまいました。結論として、次のように実行すると想定していた通りの動作になりました。shではなくbashとして実行してあげます。

$ bash difftest.sh
1c1
< aaa
---
> bbb

原因

このdiffコマンドでは、<()と記載する、プロセス展開という記法?をつかっているのですが、この記法はshでは解釈されず、bashでなら解釈されます。よってshではエラーに、bashでは正常終了したというわけです。

でも、シェバンに#!/bin/bashと記載してるし、/bin/shは/bin/bashへのシンボリックリンクじゃないの?、と思うかもしれません(私もこう思っていました)。これはその通りなのですが、実はbashスクリプトをshで実行した時はbashはshをエミュレートするようになるようです。これをPOSIX互換モードと呼ぶそうです。

つまりは、動作するのはbashなんだけど、その振る舞いはshになるということです。

ややこしい。。。

なのでbashとしての動作を期待する場合は、必ずbashコマンドで実行しましょう。

コメント

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