Bash - 使用CRLF行结尾无缝运行脚本

时间:2015-04-13 11:01:25

标签: windows bash docker newline

我正在使用VM(在我的例子中只是boot2docker)在Windows主机上运行docker容器。为了方便起见,我的源文件是从主机文件系统映射的,因此默认情况下使用Windows样式的CRLF行结尾而不是Unix样式的LF结尾文本文件。

当我尝试从docker容器运行一些.sh文件时,我会收到错误

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

有什么方法可以告诉bash / sh解释器自动将\ r \ n转换为\ n并运行文件?

当然,我可以像这样cat script.sh | tr -d "\r" | sh做一些piplelining,或甚至为此创建一个别名,但它不会涵盖一个脚本包含另一个脚本的情况。

我到目前为止找到的唯一可接受的解决方案是将Git设置为以UNIX格式签出源文件。

5 个答案:

答案 0 :(得分:5)

您可以在根文件夹中的repo中提交.gitattributes文件,以便在签出时自动告诉Git将LF行结尾应用于所有.sh文件,即使在Windows上也是如此。这样,您或其他开发人员就不必记住在您克隆repo的每台计算机上配置Git。

# Set line endings to LF, even on Windows. Otherwise, execution within Docker fails.
# See https://help.github.com/articles/dealing-with-line-endings/
*.sh text eol=lf

答案 1 :(得分:3)

对于某些脚本,解决方案ln -s /bin/bash /bin/bash^M将失败 因此,创建一个脚本/ bin / bash ^ M将dos2unix他们获得的参数并使用"$@"运行它们。

编辑: 我用以下bash ^ M脚本尝试了它:

#!/bin/bash
PROG=$1
shift
dos2unix $PROG > /dev/null 2>&1
$PROG "$@"

当您的脚本包含带点的其他脚本时,这将失败,在这种情况下,您应该避免这种解决方法并使用Unix格式。
你说你可以用Unix格式结帐,或者你可以自己更改文件 并且提交到git,将unix文件以unix格式存储在git中是一种改进。如果您真的想在Windows下编辑它们,请在之后更改编辑器或dos2unix的设置。

答案 2 :(得分:2)

我想你可以写一个像

这样的剧本
#!/bin/bash
#bash_run_unixified
#unixify and run in bash
dos2unix < "$1" | /bin/bash

并假设您使用适当的权限(sudo chmod o+r,o+x)将其保存在/ urs / local / bin / bash_run_unixified中,那么您可以在脚本前加上

#!/usr/local/bin/bash_run_unixified
#This script has CRLFs in it

如果你不想要这些不寻常的shebang线,你可以

$ ln -s /usr/local/bin/{bash_run_unixified,bash}

然后使用 (正如Walter A.所说,将它与bash^M链接起来可能是一个好主意)

#!/usr/bin/env bash

因为你的shebang行(/usr/local/bin/通常比$PATH更接近/bin的开头,所以env命令应该选择链接到{{1}的bash }})。

(提醒:我还没有测试过这些)

答案 3 :(得分:1)

我最好的解决方案是确保使用能够直接使用适当的eol风格保存的编辑器(如Notepad ++或Sublime Text)。

这样,我在boot2docker会话中不需要dos2unix任何文件。

答案 4 :(得分:0)

Visual Studio 代码也擅长将行结尾更改为 linux 或 windows 文件结尾