我正在mac上制作一个nw.js应用程序,并希望通过双击图标以开发模式运行该应用程序。第一步,我要让shell脚本正常工作。
在windows上使用vscode(我想争取时间),我创建了一个 run-nw
文件,包含以下内容:
# !/bin/bash
cd "src"
npm install
cd ..
./tools/nwjs-sdk-v0.17.3-osx-x64/nwjs.app/Contents/MacOS/nwjs "src" &
但我得到的结果是:
$ sh ./run-nw
: command not found
: No such file or directory
: command not found
: No such file or directory
Usage: npm <command>
where <command> is one of: (snip commands list)
(snip npm help)
npm@3.10.3 /usr/local/lib/node_modules/npm
: command not found
: No such file or directory
: command not found
我真的不明白:
它似乎以空行作为命令。在我的编辑器(vscode)中,我尝试替换 \r\n
与 \n
(如果 \r
制造问题),但它什么也没改变。
似乎找不到文件夹(有或没有 dirname
或者它不知道 cd
命令?
似乎它不明白 install
论据 npm
真正让我感到奇怪的是,它仍然在运行这个应用程序(如果我做了一个测试的话) npm install
手动)。。。
由于无法使其正常工作,并且怀疑文件本身有什么奇怪的地方,我直接在mac上创建了一个新的文件,这次使用的是vim。我输入了完全相同的指令,然后。。。现在它的工作没有任何问题。
两个文件的差异显示完全没有差异。
有什么区别?什么能使第一个脚本不起作用?我怎么知道?
更新
按照接受答案的建议,在错误的行尾返回后,我检查了多个内容。原来自从我抄了我的 ~/.gitconfig
在我的windows机器上,我 autocrlf=true
,所以每次我在windows下修改bash文件时,它都会将行尾重新设置为 \r\n
.
因此,除了运行dos2unix(必须在mac上使用自制软件安装),如果您使用的是git,请检查您的配置。
9条答案
按热度按时间okxuctiv1#
我在wsl中使用git时遇到了这个问题。git有一个特性,它可以根据您使用的操作系统更改文件的行尾,在windows上,它可以确保行尾是正确的
/r/n
与只使用/n
.您可以通过添加文件名来解决此问题
.gitattributes
添加到git根目录,并添加以下行:在本例中,所有文件
config
目录将只有换行符和换行符run.sh
还有文件。0lvr5msh2#
对。bash脚本对行结束非常敏感,无论是在脚本本身还是在它处理的数据中。它们应该有unix风格的行尾,即每行以换行符(十进制10,ascii中的十六进制0a)结束。
脚本中的dos/windows行尾
对于windows或dos样式的行结束符,每行都以回车符和换行符结束。您可以在的输出中看到这个不可见的字符
cat -v yourfile
:在这种情况下,回车(
^M
插入符号或\r
在c语言中,转义符号)不被视为空白。bash将shebang后面的第一行(由单个回车符组成)解释为要运行的命令/程序的名称。因为没有名为
^M
,它打印出来了: command not found
因为没有名为"src"^M
(或src^M
),它打印出来了: No such file or directory
它过去了install^M
而不是install
作为一个论据npm
导致npm
抱怨。dos/windows输入数据中的行尾
如上所述,如果您有一个带有回车符的输入文件:
然后,在编辑器和将其写入屏幕时,它看起来完全正常,但工具可能会产生奇怪的结果。例如,
grep
将无法找到明显存在的行:追加的文本将覆盖行,因为回车会将光标移到行的开头:
字符串比较似乎会失败,即使写入屏幕时字符串看起来相同:
解决方案
解决方案是将文件转换为使用unix样式的行尾。有许多方法可以实现这一点:
可以使用
dos2unix
课程:在一个功能强大的文本编辑器(sublime,notepad++,而不是notepad)中打开文件,并将其配置为使用unix行结尾保存文件,例如,使用vim,在(重新)保存之前运行以下命令:
如果你有一个版本的
sed
支持-i
或者--in-place
选项,例如gnused
,可以运行以下命令来剥离尾部回车:与其他版本的
sed
,可以使用输出重定向写入新文件。请确保为重定向目标使用不同的文件名(可以稍后重命名)。同样地
tr
翻译过滤器可用于从输入中删除不需要的字符:赛文·巴什
对于cygwin的bash端口,有一个自定义
igncr
选项,可以设置为忽略行尾中的回车(可能是因为许多用户使用本机windows程序编辑文本文件)。可以通过运行set -o igncr
.设置此选项仅适用于当前shell进程,因此在查找包含无关回车符的文件时非常有用。如果您经常遇到具有dos行结尾的shell脚本,并且希望永久设置此选项,则可以设置一个名为
SHELLOPTS
(所有大写字母)包括igncr
. bash使用此环境变量在启动时(在读取任何启动文件之前)设置shell选项。实用工具
这个
file
实用程序对于快速查看文本文件中使用的行尾非常有用。下面是它为每种文件类型打印的内容:unix行尾:
Bourne-Again shell script, ASCII text executable
mac行结尾:Bourne-Again shell script, ASCII text executable, with CR line terminators
dos行尾:Bourne-Again shell script, ASCII text executable, with CRLF line terminators
gnu版本的cat
实用程序具有-v, --show-nonprinting
显示非打印字符的选项。这个
dos2unix
这个实用程序是专门为在unix、mac和dos行尾之间转换文本文件而编写的。有用的链接
wikipedia有一篇很好的文章,介绍了标记一行文本结尾的许多不同方法,这种编码的历史,以及在不同的操作系统、编程语言和internet协议(如ftp)中如何处理换行。
具有经典mac os行尾的文件
对于经典的mac os(os x之前的版本),每行都以回车结束(十进制13,十六进制0d,ascii)。如果脚本文件以这样的行结尾保存,bash将只看到一行长的行,如下所示:
因为这条长长的线是从一只章鱼开始的(
#
),bash将行(和整个文件)视为单个注解。注:2001年,苹果推出了基于bsd衍生的nextstep操作系统的MacOSX。因此,osx也使用unix风格的lf-only行尾,从那时起,以cr结尾的文本文件变得极为罕见。不过,我认为有必要展示bash如何尝试解释这些文件。
j5fpnvbx3#
在mac/linux上最简单的方法是使用“touch”命令创建一个文件,用vi或vim编辑器打开这个文件,粘贴代码并保存。这将自动删除windows字符。
fkaflof64#
在jetbrains产品(pycharm、phpstorm、idea等)上,您需要单击
CRLF
/LF
在两种行分隔符之间切换的步骤(\r\n
以及\n
).kuuvgm7e5#
如果您使用的是bbedit这样的文本编辑器,您可以在状态栏上进行编辑。有一个可供切换的选项。
inb24sb26#
摆脱不需要的cr('\r')字符的另一种方法是运行
tr
命令,例如:8iwquhpp7#
为了完整起见,我将指出另一种解决方案,它可以永久地解决这个问题,而无需一直运行dos2unix:
3vpjnl9f8#
如果问题是文件名中包含
^M
最后,您可以使用您应该首先修复导致这些文件名称损坏的原因(可能是创建这些文件的脚本)
dos2unix
但有时这是不可行的。这个
$'\r'
语法是特定于bash的;如果你有一个不同的shell,也许你需要使用其他的符号。也许还能看到sh和bash之间的区别wooyq4lh9#
我正试图从windows启动docker容器,结果是:
我使用的是gitbash,问题出在git配置上,然后我只做了下面的步骤,就成功了。它将git配置为在 checkout 时不转换行尾:
git config --global core.autocrlf input
删除本地存储库再克隆一次。
非常感谢jason harmon的链接:https://forums.docker.com/t/error-while-running-docker-code-in-powershell/34059/6
在那之前,我试过这个,但没用:
dos2unix scriptname.sh
sed -i -e 's/\r$//' scriptname.shsed -i -e 's/^M$//' scriptname.sh