初学shell的时候,总听到群里的大牛说不要使用Windows自带的notepad编写shell。然而,一直不解其中的原因。接下来,咱们动手实践一下,了解其中的来龙去脉。
在Windows下,打开notepad,敲打以下代码:
#! /bin/bashecho "This is the first line \of the script."echo "This is the second line \of the script."保存为test1。然后将这个文件复制到Linux下。打开这个文件,会看到文件的内容与之前在Windows下编辑的文本文件并无区别。
在Linux下,使用vi编辑test2文件,加入同样的内容,然后保存。
接下来,分别运行这两个文件(注意:运行前先赋予这两个文件以可执行权限)。对于test2,得到如下输出:
$ ./test2This is the first line of the script.This is the second line of the script.对于test1,则得到这样的输出:
$ ./test1bash: ./test1: /bin/bash^M: badinterpreter: No such file or directory也就是说,在Windows下用notepad编写的shell运行出错了。从报错信息可以看出,从header这一行就已经出错了,header这一行本来是要告诉我们的内核使用Bash这个命令解释器,它的路径位于/bin/bash。可是bash却告诉我们无此文件。究其原因,是^M这个字符影响了header一行对于命令解释器的正常识别。那^M这个字符又是什么呢?
不用的操作系统使用不同的字符来表示换行。Unix/Linux使用单个的换行(Line Feed,LF)符作为换行的标记。Windows/DOS使用2个字符:回车(Carriage Return,CR)符和换行符(LF)。MacOS使用CR。^M即为我们在使用Windows的notepad产生的回车符。更多信息可参见维基百科上关于Newline的解释:
对于Linux Deepin甚至其他发行版本来说,一个比较通用的方法是使用tr工具来删除多余的回车符,因为它不需要安装额外的工具,且便于理解。
tr -d '\r' < test1 > tmp && mv tmp test2使用这条命令删除多余的回车符后,该脚本即可正常运行。tr是translate或transliterate的缩写。tr工具从其标准输入(stdin)中转换、缩减或删除字符,并写道标准输出(stdout)。其基本句法为:
tr [options] set1 [set2]在这里,tr从文件test1中读入,将其中的回车符(\r)删除后输出为文件tmp,然后又将文件tmp重命名为test2。对于tr的更多用法,可查看其man page。