Bash で「/bin/bash^M: bad interpreter」が解決できない
エラー文末尾の ^M は改行コードが CRLF になっている印である。#! 行の末尾に付いた \r までインタプリタ名の一部として扱われ、そんなパスは存在しないので落ちる。
改行を LF に直せば解消する。
公開:
要約
bad interpreter: No such file or directory は、#! 行に書いたインタプリタが見つからないときのエラーである。
パスの綴りが正しいのにこれが出て、しかもエラー文に ^M が混じっているなら、原因は改行コードである。
$ ./setup.sh
bash: ./setup.sh: /bin/bash^M: bad interpreter: No such file or directory^M はキャリッジリターン(\r)の表示である。
CRLF のファイルでは #!/bin/bash の行末が /bin/bash\r となり、カーネルは /bin/bash\r という名前のファイルを探しに行って失敗する。/bin/bash は存在するのに「無い」と言われるのはこのためである。
よくある原因
- Windows のエディタで保存した: 既定の改行コードが CRLF のまま
.shを作ると必ずこうなる。 - Git の自動変換:
core.autocrlf=trueの Windows 環境では、チェックアウト時に LF が CRLF へ変換される。
WSL やコンテナから同じ作業ツリーを触ると露見する。 .gitattributesで固定していない: リポジトリ側で改行を宣言していないと、開発者ごとの設定に左右される。- 共有フォルダ・zip 経由での持ち込み: 途中の経路で変換されることがある。
解決策
1. 改行を LF に直す
sed -i 's/\r$//' setup.shdos2unix setup.sh でもよい。
直ったかどうかは file で確認できる。
$ file setup.sh
setup.sh: Bourne-Again shell script, ASCII text executablewith CRLF line terminators が消えていれば直っている。
2. .gitattributes で再発を止める
*.sh text eol=lfgitattributes の仕様(新しいタブで開く)どおり、text で索引上は LF に正規化し、eol=lf でチェックアウト時も LF のままにする。
個人の core.autocrlf 設定より属性が優先されるので、リポジトリ全体で改行が揃う。
1 度書いたら git add --renormalize . で既存ファイルにも適用する。
3. 直せないときの回避
bash setup.shインタプリタを明示すれば #! 行は単なるコメントとして読み飛ばされるため、CRLF のままでも起動はする。
ただし本文中の \r が変数の値に紛れ込んで比較に失敗するなど別の不具合を招くので、あくまで一時しのぎである。
改行そのものを直すのが本筋になる。