Bash脚本 - "/bin/bash^M: 坏的解释器: 没有那个文件或目录"

759

我正在使用这个教程学习bash脚本,以便自动化一些任务。
我使用putty连接到服务器。

脚本位于.../Documents/LOG中,内容如下:

#!/bin/bash
# My first script
echo "Hello World!"

我针对 读/写/执行权限 执行了以下操作

chmod 755 my_script

然后,当我输入./my_script时,我会得到标题中给出的错误。

有些类似的问题想要看到这些,所以我认为它们可能会对你有帮助:

$ which bash
/bin/bash

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/bin/mh

我尝试将当前目录添加到PATH,但这并不起作用…


我使用Notepad++在Windows中创建了文件,然后使用WinSCP将文件复制到服务器上。我知道这不是理想的做法。 - cartonn
1
看看我的回答,这很可能是问题所在。 - cowls
16
我投票支持重新开放这个问题,因为标题包含/bin/bash^M: bad interpreter: No such file or directory,让我通过谷歌搜索直接找到了解决方案。而“重复”问题没有。 - Jim Tough
顺便说一下 - 当我复制一个 .bat 文件并将扩展名更改为 .sh 时,我遇到了这个问题。我的计划是将批处理代码重写为 shell。创建一个新的 .sh 文件并粘贴我的代码就解决了问题。 - drake7
我在同时使用WSL2和运行Docker后端时遇到了这个问题。关闭Docker并执行wsl --shutdown,然后再次启动它可以解决这个问题。 - Nicolás de Ory
显示剩余2条评论
11个回答

1200
可能的原因是您在Windows上保存了文件,并将CR LF作为行尾(\r\n)。
请在终端中运行以下命令:
sed -i -e 's/\r$//' scriptname.sh

(当然,将scriptname.sh更改为您的文件名)
该命令将删除那些CR字符,这将使这些行以LF\n)作为结尾,Bash将能够通过运行来读取和执行该文件。
./scriptname.sh

7
如果这种方法不奏效,尝试使用命令 sed -i -e 's/^M$//' scriptname.sh。(按下 Ctrl+V Ctrl+M 插入 ^M)。 - youhans
4
这对我没有用,包括点号。然而,原始答案有一个解决方案适用于我:在Vim中打开文件并在保存之前运行以下命令::set fileformat=unix,该命令列在名为“shell脚本是否对编码和行结尾敏感”的SO问题下,对我有效。 - Jazzmine
2
如果在没有安装dos2unix的Docker容器上工作,可以获得奖励。虽然在我的情况下无法覆盖脚本,所以我的命令看起来像这样:cat scriptname.sh | sed -e 's/\r$//' > fixedscriptname.sh - Rhubarb
3
如果有帮助的话,我使用了以下命令: sed -i -e 's/\r$//' *.sh 这个命令将所有的sh文件转换为可用的格式。 - Mark N Hopgood
30
@Robert Molina,Windows在行末除了添加\n外还会添加回车符号。这个命令使用Linux流编辑命令(sed)通过将\r替换为空字符串来移除它。请注意,此操作不会改变原始含义。 - Michael Szczepaniak
显示剩余4条评论

844

我曾在Windows环境下创建脚本,然后将其移植到Unix环境下运行时遇到了这个问题。

尝试在脚本上运行 dos2unix

http://dos2unix.sourceforge.net/

或者在您的Unix环境中使用 vi 重写脚本并进行测试。

Unix 使用不同的行结束符,因此无法读取您在 Windows 上创建的文件。因此它会将 ^M 视为非法字符。

如果要在 Windows 上编写文件,然后移植,请确保您的编辑器设置为以 UNIX 格式创建文件。

在 notepad++ 中,在屏幕右下角显示文档格式。默认情况下,它将显示 Dos\Windows。要更改它,前往

  • 设置->首选项
  • 新建文档/默认目录选项卡
  • 选择格式为 Unix 并关闭
  • 创建一个新文档

44
您可以右键单击底部右侧的Dos\Windows文本,将其更改为Unix。 - Hardy
4
对于如此不太可能的解决方案,我给你点赞!!我正在使用UltraEdit。要在那里实现相同的操作,请选择 文件-> 转换-> DOS转Unix。 - imnd_neel
我在记事本中打开脚本,然后将其粘贴到Putty Shell中,最后保存。目前一切都很好。谢谢你的回答。 - Dylan B
7
如果你使用Sublime Text 3编辑器,你可以通过选择 View->Line Endings->Unix 来将文本行结束符从Windows格式转换为Linux格式,然后按下 Ctrl+S 来保存你的脚本。 - Alfredo Capobianchi
5
在 VSCode 中,您可以将底部右侧的“Linefeed”选项从“CRLF”更改为“LF”,以实现与此帖子相同的效果。 - Snapstromegon
显示剩余11条评论

162

如果你在Windows或Mac上使用 Sublime Text 编辑脚本:

点击 View > Line Endings > Unix 并且再次进行保存

enter image description here


完美修复,谢谢。 - Devon
1
我最喜欢的答案。没有其他方法这么容易。 - App Dev Guy
1
它起作用了。但我能知道需要执行此操作的原因吗? - Rahal Kanishka
完美的修复,谢谢 - Thiago Magalhães
非常棒。非常感谢。 - Raju Ahmed
我们能将这个设为默认行为吗?也就是说,任何在Sublime中编辑并保存的文件都会自动完成这个操作。 - user408108

76

在notepad++中,您可以通过按以下方式对文件进行特定设置:

编辑-->行尾转换-->UNIX/OSX格式

输入图像描述


2
那个有效了。谢谢。 - Noman Riffat
this is it! thanks! - KansaiRobot
对我很有用。节省了我的时间和精力。 - Muhammad Tariq
对于我的Docker初始化脚本也起作用。 - Mehmet Kasalak

60

这是由于在Windows中编辑文件后导入并在Unix中执行引起的。

dos2unix -k -o 文件名 可以解决问题。


2
对不起,它对我没有用。 - raja777m
1
-k:保持输出文件的日期戳与输入文件相同。-o:旧文件模式。将文件FILE转换并覆盖输出到它。程序默认在此模式下运行。 - Martin Schneider

20

问题出在 DOS 的行尾符。使用以下方法可以将其转换为 Unix 格式。

dos2unix file_name

注意:您可能需要首先使用yum install dos2unix安装dos2unix。

另一种方法是使用sed命令搜索和替换DOS行尾字符为Unix格式:

$sed -i -e 's/\r$//' your_script.sh

20

你的文件使用Windows换行符,这会让Linux感到困惑。

移除多余的CR字符。您可以使用以下命令完成:

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

这就是我需要的魔法,当我无法在Windows文件系统上运行脚本时。 - Throttlehead

10
我能够通过在Gedit中打开脚本并选择正确的行尾选项来解决此问题:

文件 > 另存为...

另存为提示框的左下角,有字符编码和行尾的下拉菜单。将行尾从Windows更改为Unix/Linux,然后保存。

在gedit的“另存为”提示框中将“行尾”选项设置为“Linux/Unix”


使用 Mousepad > Document>Line Ending>Unix (LF); Save 对我有效。 - ivan866

8
对于使用 Eclipse 的用户,您可以直接从菜单 文件 > 转换行分隔符到 > Unix (LF, \n, 0Α, ¶) 更改文件编码:

Eclipse change file encoding

或在 窗口 > 首选项 > 通用 > 工作空间 面板中更改 新建文本文件行分隔符其他:Unix

Eclipse workspace settings


“File > Convert Line Delimiters To” 可以实现此功能,但是 “Window > Preferences > General > Workspace > Unix” 似乎没有帮助。 - Panu Haaramo
1
@PanuHaaramo,该设置适用于所有新创建的文件。如果您有一个已经创建的文件,则必须像第一张截图中那样进行转换。 - Christos Lytras

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接