如果从 Windows 复制的脚本看起来很正常,但 macOS 提示“bad interpreter”或命令行为表现得像带有多余字符,请检查是否存在 Windows CRLF 换行符。macOS 命令行工具需要 LF。你可以确认文件类型,使用 macOS 自带的工具转换副本,然后重新运行修复后的脚本。

为什么换行符会导致脚本在 macOS 上报错

换行符是标记文本行结尾的一个字符(或一对字符)。macOS 命令行工具使用 LF (\n);Windows 通常使用 CRLF (\r\n)。在 CRLF 格式下,Unix 命令读取该行时,回车符可能会继续附着在行尾。Apple 的文档指出,这个多余的字符可能会导致命令行工具和脚本出现异常行为。Apple Shell 脚本指南

常见的线索包括 /bin/bash^M: bad interpreter、似乎包含末尾 \r 的 command-not-found 报错信息,或者尽管肉眼看到的脚本内容完全正确但解析仍然失败。这些症状也可能有其他原因;检查文件是实用的第一步,但本身并不能作为绝对证据。

检查脚本的换行符格式

打开“终端”,切换到包含该脚本的文件夹,然后使用 file 进行检查。为文件名加上引号,以便空格和 Shell 元字符按字面含义处理:

cd "$HOME/Downloads"
file "my script.sh"

如果输出显示该文件包含 CRLF 行终止符(CRLF line terminators),则支持这一诊断。如果报告为 LF,则换行符可能不是导致问题的原因。macOS 的 file 命令的描述可能会有所不同,混合换行符可能无法清晰汇总,因此也需要结合错误信息和脚本源码上下文来判断。要检查某行的特定字节,macOS 还包含了 od;例如:

od -An -tx1 -c "my script.sh" | head

0d 0a 序列代表 CRLF;单独的 0a 则是 LF。在未核实其位置之前,请勿将文件中其他位置的回车符直接视为换行符。

在不覆盖原文件的情况下将 CRLF 转换为 LF

Apple 的 macOS 指南指出,macOS 并未自带 dos2unix,并建议改用 tr 或 sed。对于 CRLF 脚本,可将回车符移除并输出到单独的文件中,同时保留原文件作为备份:

cp -p "my script.sh" "my script.sh.bak"
tr -d '\r' < "my script.sh" > "my script.lf.sh"
file "my script.lf.sh"

这种方法适用于不必要的回车符属于 Windows 换行符的情况。它会删除文件中的每一个 CR 字节,因此如果文件有意使用回车符作为数据,请避免使用此方法。使用单独的输出文件还可以避免截断输入内容:直接重定向回原文件可能会在转换完成之前清空该文件。

在替换任何内容之前,请先检查新文件。如果内容看起来正确,且 file 显示为 LF 换行符,请尝试使用预期的解释器运行它。例如对于 Bash 脚本:

bash "my script.lf.sh"

通过 bash 运行不需要可执行权限位或有效的 shebang。如果需要将其作为 ./my script.lf.sh 直接运行,请赋予其可执行权限,并确保其第一行指定了可用的解释器,例如 #!/bin/bash:

chmod +x "my script.lf.sh"
"./my script.lf.sh"

检查修复后的文件无误后,你可以在“访达”或“终端”中替换原文件。在脚本按预期工作之前,请保留 .bak 副本。如果该脚本属于共享项目的一部分,请在其源编辑器或代码仓库工作流中进行相同的换行符修正,以防止再次保存文件时问题重现。

如果错误依然存在

如果 file 已经显示为 LF,或者转换后未能解决失败问题,请仔细阅读具体的错误信息,并检查第一行指定的解释器。解释器缺失、路径无效、语法错误或缺少执行权限都可能导致类似的失败。该脚本还可能依赖了其指定解释器中不可用的命令或 Shell 功能。

“文本编辑”可以打开和保存纯文本文档,但 Apple 记录的“文本编辑”指南中并未描述换行符选择器。对于此类修复,请使用上述“终端”转换方法,或使用明确显示并允许更改换行符的代码编辑器;保存后请对文件进行验证。Apple“文本编辑”指南

实用的步骤是:识别文件格式、保留备份、仅在存在 CRLF 时进行转换,然后使用预期的解释器重新运行。这样可以确保修复仅针对该文件,而不会更改不相关的脚本。

参考资料