Bootstrap

2021.08.29_Android_各系统间换行符不同引起的无法执行shell脚本,提示no such file or directory

        最新在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

;