できない.dev

Bash で「/bin/bash^M: bad interpreter」が解決できない

エラー文末尾の ^M は改行コードが CRLF になっている印である。#! 行の末尾に付いた \r までインタプリタ名の一部として扱われ、そんなパスは存在しないので落ちる。
改行を LF に直せば解消する。

公開: 更新:

実行例あり(2026-09-11 に実環境で検証)

要約

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 は存在するのに「無い」と言われるのはこのためである。

ただし、この表示は bash の版に依存する。
同じ CRLF のスクリプトでも、bash 5.1.16(Ubuntu 22.04)では上のとおり ^M 付きで出る一方、bash 5.2.21(Ubuntu 24.04)では bash: ./setup.sh: cannot execute: required file not found となり、インタプリタ名そのものが出ない。
メッセージに ^M が無くても、#! 行の改行コードを疑う価値はある。

実行例

実際に上記の手順を ubuntu:22.04(Bash 5.1.16)で動かすと、od -c で行末に \r が見えるスクリプトは /bin/bash^M: bad interpreter で終了コード 126 になり、sed で \r を取り除いた後は setup done を出力して終了コード 0 になった。
改行を直していないファイルも bash legacy.sh と明示して起動すれば、終了コード 0 で最後まで実行された。

$ od -c setup.sh
0000000   #   !   /   b   i   n   /   b   a   s   h  \r  \n   e   c   h
0000020   o       "   s   e   t   u   p       d   o   n   e   "  \r  \n
0000040
$ ./setup.sh
bash: ./setup.sh: /bin/bash^M: bad interpreter: No such file or directory
$ echo $?
126
$ sed -i 's/\r$//' setup.sh
$ od -c setup.sh
0000000   #   !   /   b   i   n   /   b   a   s   h  \n   e   c   h   o
0000020       "   s   e   t   u   p       d   o   n   e   "  \n
0000036
$ ./setup.sh
setup done
$ echo $?
0
$ bash legacy.sh
crlf still here
$ echo $?
0

— 2026-09-11 時点の出力

検証環境

検証日
実行環境
ubuntu:22.04Ubuntu 22.04.5 LTS
バージョン
  • Bash 5.1.16

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

よくある原因

  1. Windows のエディタで保存した: 既定の改行コードが CRLF のまま .sh を作ると必ずこうなる。
  2. Git の自動変換: core.autocrlf=true の Windows 環境では、チェックアウト時に LF が CRLF へ変換される。
    WSL やコンテナから同じ作業ツリーを触ると露見する。
  3. .gitattributes で固定していない: リポジトリ側で改行を宣言していないと、開発者ごとの設定に左右される。
  4. 共有フォルダ・zip 経由での持ち込み: 途中の経路で変換されることがある。

解決策

1. 改行を LF に直す

sed -i 's/\r$//' setup.sh

dos2unix setup.sh でもよい。
直ったかどうかは file で確認できる。

$ file setup.sh
setup.sh: Bourne-Again shell script, ASCII text executable

with CRLF line terminators が消えていれば直っている。

2. .gitattributes で再発を止める

*.sh text eol=lf

gitattributes の仕様(新しいタブで開く)どおり、text で索引上は LF に正規化し、eol=lf でチェックアウト時も LF のままにする。
個人の core.autocrlf 設定より属性が優先されるので、リポジトリ全体で改行が揃う。
1 度書いたら git add --renormalize . で既存ファイルにも適用する。

3. 直せないときの回避

bash setup.sh

インタプリタを明示すれば #! 行は単なるコメントとして読み飛ばされるため、CRLF のままでも起動はする。
ただし本文中の \r が変数の値に紛れ込んで比較に失敗するなど別の不具合を招くので、あくまで一時しのぎである。
改行そのものを直すのが本筋になる。

この記事は役立ちましたか?