Sửa lỗi 'bad interpreter: No such file or directory' Do Ký Tự Xuống Dòng CRLF Kiểu Windows trên macOS

beginner🍎 macOS2026-05-04| macOS (tất cả phiên bản), bash/zsh shell, shell script được chỉnh sửa trên Windows hoặc clone từ repo có ký tự xuống dòng CRLF

Error Message

bash: ./script.sh: /bin/bash^M: bad interpreter: No such file or directory
#bash#shell#crlf#macos

TL;DR

Shell script của bạn có ký tự xuống dòng kiểu Windows (CRLF) thay vì kiểu Unix (LF). Ký tự ^M trong thông báo lỗi là một ký tự carriage return (\r) bám vào cuối chuỗi /bin/bash, khiến dòng shebang không đọc được. Sửa bằng lệnh:

sed -i '' 's/\r//' script.sh

Hoặc dùng dos2unix nếu bạn đã cài:

dos2unix script.sh

Sau đó chạy lại script của bạn.

Điều Gì Đang Xảy Ra

Khi bạn thấy lỗi này:

bash: ./script.sh: /bin/bash^M: bad interpreter: No such file or directory

Ký tự ^M đó không phải cờ bí ẩn gì. Đó là một ký tự carriage return (\r, ASCII 13) nằm ở cuối dòng shebang. Với macOS, dòng đầu tiên trong script của bạn trông như sau:

#!/bin/bash\r\n

Kernel cố tìm trình thông dịch tại đường dẫn /bin/bash\r. Đường dẫn đó không tồn tại. Script sẽ không chạy được.

Script bị dính CRLF khi được tạo hoặc chỉnh sửa trên Windows — Notepad, VS Code với cài đặt CRLF mặc định, hay WSL với git cấu hình sai — rồi đưa sang macOS. Windows kết thúc dòng bằng \r\n. Unix và macOS chỉ chờ \n.

Bốn cách phổ biến khiến CRLF lọt vào:

  • Clone repo có file .gitattributes ép checkout theo kiểu CRLF
  • Sao chép script từ máy Windows qua USB hoặc chia sẻ file
  • Chỉnh sửa trong VS Code khi files.eol được đặt thành \r\n
  • Tải script từ trang web lưu trữ file với ký tự xuống dòng CRLF

Xác Nhận Vấn Đề Trước

Hãy xác nhận CRLF thực sự là nguyên nhân trước khi làm bất cứ điều gì:

cat -A script.sh | head -5

Các dòng kết thúc bằng ^M$ nghĩa là CRLF. File Unix sạch chỉ hiển thị $.

Lệnh file cho bạn câu trả lời rõ ràng:

file script.sh
# Có CRLF: script.sh: Bourne-Again shell script, ASCII text executable, with CRLF line terminators
# Sạch:    script.sh: Bourne-Again shell script, ASCII text executable

Để xem byte thô, lệnh xxd cho bạn thấy chính xác nội dung file:

xxd script.sh | head -3

CRLF hiển thị dưới dạng các cặp 0d 0a. Ký tự xuống dòng Unix chỉ là 0a.

Các Cách Sửa

Cách 1: sed (có sẵn trên macOS, không cần cài thêm)

sed -i '' 's/\r//' script.sh

Cú pháp -i '' là đặc trưng của macOS — GNU sed trên Linux bỏ chuỗi rỗng và chỉ dùng -i. Lệnh này xóa tất cả ký tự \r trực tiếp trong file.

Cách 2: dos2unix (công cụ chuyên dụng cho việc này)

Cài đặt trước:

brew install dos2unix

Sau đó chuyển đổi:

dos2unix script.sh

Có cả một thư mục chứa shell script? Một lệnh xử lý tất cả:

find . -name "*.sh" -exec dos2unix {} \;

Cách 3: tr (tùy chọn có sẵn khác)

tr -d '\r'  script_fixed.sh
mv script_fixed.sh script.sh

tr không thể chỉnh sửa file trực tiếp, nên bạn cần bước tạo file trung gian này.

Cách 4: Sửa trong VS Code trước khi commit

Nhấp vào CRLF ở góc dưới bên phải của VS Code và chuyển sang LF, rồi lưu lại. Để đặt LF làm mặc định vĩnh viễn cho tất cả file mới, thêm dòng này vào cài đặt VS Code:

{
  "files.eol": "\n"
}

Cách 5: Sửa ở cấp độ git (ngăn tái phát)

Nếu CRLF cứ xuất hiện lại sau mỗi lần checkout, git đang tự động chuyển đổi ký tự xuống dòng. Hãy tắt tính năng này:

# Chỉ cho repo này
git config core.autocrlf false

# Hoặc toàn cục
git config --global core.autocrlf input

Cách sửa bền vững hơn là tạo file .gitattributes và commit vào chính repo đó:

# .gitattributes
*.sh text eol=lf
*.bash text eol=lf

Commit một lần, và mọi người đóng góp — Windows, macOS, Linux — đều nhận được ký tự xuống dòng LF khi checkout. Không cần cấu hình từng máy riêng lẻ.

Kiểm Tra Kết Quả Sau Khi Sửa

Chạy lại lệnh kiểm tra như trước:

file script.sh
# Kết quả mong đợi: ASCII text executable (không còn nhắc đến CRLF)

Cấp quyền thực thi và chạy script:

chmod +x script.sh
./script.sh

Lỗi /bin/bash^M: bad interpreter đã biến mất.

Tóm Tắt Nhanh

  • Triệu chứng: Có ^M trong thông báo lỗi, script không chạy được
  • Nguyên nhân: Ký tự xuống dòng CRLF từ trình soạn thảo Windows hoặc cấu hình git sai
  • Sửa nhanh nhất: sed -i '' 's/\r//' script.sh (không cần cài thêm)
  • Sửa lâu dài tốt nhất: File .gitattributes với dòng *.sh text eol=lf

Related Error Notes