最新在Android开发中,在Windows上编辑好一个xx.sh脚本文件,放入android系统中,配置好权限,执行时出错,提示:error: no such file or directory, 文件是存在的,为什么执行错误?
原因就在于:Window系统下编辑的文件内容使用了Windows换行符,这与Linux下的换行符是不一样的,自然就识别不了。
注:以下实验的文件cc.sh是Windows下生成的。
操作系统文件换行符
换行符‘\n’和回车符‘\r’
在ASCII中存在这样两个字符CR(编码为13)和 LF(编码为10),在编程中我们一般称其分别为 '\r' 和 '\n' 。
字符LF -- '\n' -- 换行符(即另起一行 newline) -- 对应符号^$;
字符CR -- '\r' -- 回车符(即回到一行的开头 return)-- 对应符号^M;
它们被用来作为换行标志,但在不同系统中换行标志又不一样。下面是不同操作系统采用不同的换行符:
在微软的MS-DOS和Windows中,使用“回车CR('\r')”和“换行LF('\n')”两个字符作为换行符。
Windows系统里面,每行结尾是 回车+换行(CR+LF),即“\r\n”;
Unix和类Unix(如Linux)系统里,每行结尾只有 换行CR,即“\n”;
Mac OS X之前系统里,每行结尾是 回车CR 即'\r';
Mac OS X系统里,每行结尾是 换行CR,即“\n”。
如何查看文件的换行符类型?
在Unix中查看换行符的几种比较常用的方法:
第一种使用 "cat -A [Filename]" 查看,看到的为一个Windows形式的换行符,\r对应符号^M,\n对应符号$.
ubuntu@root:/workplace/tmp$ cat -A cc.sh
123^M$
223^M$
323^M$
第二种使用vi编辑器查看,然后使用”:set list”命令显示特殊字符(vi 打开文件后,按下shift + :两个键,然后输入set list,最后按enter键)
ubuntu@root:/workplace/tmp$ vi cc.sh
123$
223$
323$
:set list
怎么^M还是没显示出来,需要用VI的二进制模式(“vi -b [FileName]”)打开,才能够显示出^M:
ubuntu@root:/workplace/tmp$ vi -b cc.sh
123^M$
223^M$
323^M$
:set list
第三种 使用vi编辑器查看,然后使用“:set ff?”
ubuntu@root:/workplace/tmp$ vi cc.sh
123
223
323
:set ff?
底部显示格式:fileformat=dos
注意这种方式不能使用vi 二进制模式打开。
不同系统间文件结尾换行符如何相互转换?
以下展示三种办法:
(1) 第一种使用VI: 使用VI普通模式打开文件,然后运行命令
"set ff=unix" 则可以将源文件换行符转换为Linux换行符,命令中ff的全称为file encoding;
"set ff=dos" 则可以将源文件换行符转换为Windows换行符;
"set ff=mac" 则可以将源文件换行符转换为MAC OS换行符。
(2) 使用"dos2unix"系列命令,如下所示
ubuntu@root:/workplace/tmp$ dos2unix cc.sh
dos2unix: converting file cc.sh to UNIX format ...
此外还有命令:unix2dos unix2mac mac2unix
(3)使用sed命令删除\r字符:
ubuntu@root:/workplace/tmp$ sed -i 's/\r//g' cc.sh
批量文件处理换行符转换
需要自己写一个脚本把某个目录下的文件批量转换。
#!/bin/sh
#CheckInput
#Check Whether the input is valid
#0 means not valid
CheckInput()
{
ret=1;
#Check the number of parameter
#And Check whether the argument is a folder
if [ $# -lt 1 ]
then
echo "Please use the command like ./dos2u.sh [Folder]";
ret=0
elif [ ! -d $1 ]
then
echo "Please use an invalid Folder as the shell argument";
ret=0
fi
return $ret;
}
#TraverseFolder
#Traser all the files under the folder
TraverseFolder()
{
oldPath=`pwd`
cd $1;
for file in `ls`
do
if [ -d $file ]
then
TraverseFolder $file;
else
#echo $file;
#sed -i 's/\r//g' $file
dos2unix $file
fi
done
cd $oldPath;
}
CheckInput $*
if [ $ret -ne 1 ]
then
exit -1
fi
TraverseFolder $1
参考文章:
https://blog.csdn.net/cjf_iceking/article/details/47836201