我有这个脚本:
echo $HOME
cd $HOME
cd /
cd /usr/local/src/
当我这样运行时
. script.sh
我得到这个输出:
/home/user
: No such file or directory
: No such file or directory
: No such file or directory
如果我正常运行它(我#!/bin/bash
在第一行之前添加)
sh script.sh
我得到这个输出:
: not found.sh: 2: script.sh
/home/user
script.sh: 3: Can't cd to /home/user
script.sh: 4: Can't cd to /
script.sh: 5: Can't cd to /usr/local/src/
$HOME
该脚本每次都从目录运行。如果我从 shell 中一一运行每个命令,它执行时不会出现问题(cd $HOME
从内部调用$HOME
根本不会更改目录)。
我必须做什么才能使这项工作成功?
答案1
您的脚本中有 CR (^M) 字符。将其转换为具有 Unix 行尾(仅 LF)。以便携的方式:
tr -d '\r' < your_script > output_script
基于 Olivier Dulac 对 CR 字符发生情况的评论的一些解释: 首先,在 shell 语言中,CR 字符不被视为特殊字符,例如不被视为空格并且不被忽略。我写如下^M
。
该行中,输出了后面跟着换行
echo $HOME^M
的内容。输出 CR 字符将光标放在第一列上,但由于紧随其后的是换行符,因此这没有明显的效果。$HOME
^M
在该
cd $HOME^M
行中,由于 和 CR 字符之间没有空格$HOME
,因此它们都在同一个参数中$HOME^M
,并且该目录不存在。在错误消息中,$HOME
只是输出后面的 CR 字符,将光标放在第一列上,这样行首就会被消息的其余部分覆盖(如果有的话): ": No such file or directory" with bash (你的第一个例子),没有破折号(你的第二个例子sh script.sh
,#!/bin/bash
因为你明确要求运行脚本而被忽略sh
,这在你的情况下似乎是破折号)。错误消息完全取决于 shell。例如,zsh 检测到 CR 字符不可打印并输出如下消息:cd: 没有这样的文件或目录: /usr/local/src/^M
(使用字符“^”和“M”,而不是 CR 字符),这使得人们可以更轻松地检测问题的原因。否则,您需要将 stderr 重定向/管道到某个可以显示特殊字符的实用程序,例如cat -ve
Olivier 建议的,或者到hd
,它给出流的字节序列。
答案2
如果您使用,set -x
您会注意到为什么获取文件失败:
$ . test.sh
+ . test.sh
++ echo $'/home/braiam\r'
/home/braiam
++ cd $'/home/braiam\r'
: No such file or directory
++ cd $'/\r'
: No such file or directory
++ cd $'/usr/local/src/\r'
: No such file or directory
正如vinc17所说,只需删除\r
脚本的一部分就可以了。您可以使用他的解决方案,或者dos2unix script.sh
也使用 ,sed -i 's/\r//' script.sh
答案3
您也可以使用以下命令删除 CR 字符。
perl -p -i -e "s/\r//g" script.sh
如果您正在使用六/维姆,你可以这样做,
:set ff=unix
答案4
我遇到了同样的问题,我通过将 EOL 字符转换为 UNIX 格式来修复它。一个简单的方法是:
- 将文件加载到 Notepad++ 中
- 选择所有要转换的文本(Ctrl + A)
- 编辑 > EOL 转换 > UNIX
- 保存文件
如果已经是 UNIX 格式,请选择另一种格式 (Windows),然后返回 UNIX