Windows & Unix 文件格式差异及win2unix转换脚本

时间:2021-06-13 14:53:28

(1)问题提出
我们可能会遇到过这样一些困惑:
A, 如何查看一个文件或数据流的二进制格式(以十六进制格式显示)?
B,为什么在 windows下编辑的 shell 脚本在 Unix下不能执行?为什么在 windows下编辑的 C 源文件在有些 gcc 编译器下不能编译?
C,为什么我在 vi 等编辑器下打开一个文本文件会包含 ^M,如何把它去掉?为什么我在 windows 上用记事本打开 unix上的文件,文件都不换行?

(2)分析与方案

A,如何查看一个文件的二进制格式(以十六进制格式显示)?
方法一:在 UtraEdit 使用 Ctrl + H 切换到十六进制编辑模式。** 注意 ** :此方法一有缺陷,它会将行末的单个"换行符"显示成 "回车" + "换行" 两个字符。

方法二:使用文件或流的二进制查看工具 fbin。

B,为什么在 windows下编辑的 shell 脚本在 Unix下不能执行?为什么在 windows下编辑的 C 源文件在有些 gcc 编译器下不能编译?

原因分析:unix 的 shell 脚本不能识别 "回车符" (即:CR,'\r'),Windows 文件格式换行时,总是以 "回车" + "换行" ,导致 unix 下的 shell 无法正常解释。解决方法:就是把 windows 格式的中的 "回车" 符删除。

方法一:使用 vi 打开源文件,把 '\r\n' 替换成 '\n' ;** 缺点 ** :不适合大量文件的批量作业。

方法二:使用 UtraEdit 把 Windows 格式的文件转换成 Unix 格式。文件-->转换-->Unix转DOS;** 缺点 ** :不适合大量文件的批量作业。

方法三:Unix 下的 dos2unix 命令,如 $ dos2unix -k xx.c;** 缺点 ** :此方法有一致命缺陷,它会改变原来的文件属性,如一个可执行 shell 脚本的可执行属性及其它属性,转换后都将会丢掉;** 优点 ** :适合大量普通文件本文件的批量作业。

方法四: win2unix (windows,unix 均可使用),功能类似 dos2unix,如 win2unix xx.c;** 优点** :克服了 dos2unix 的所有缺点,它能保留源文件的任何属性。还适合大量文件的批量作业。

C,为什么我在vi 等编器下打开一个文本文件会包含^M,如何把它去掉? 为什么我在windows上用记事本打开unix上的文件,文件都不换行?

原因分析:要解决这个问题,必先弄清 unix 与 windows 文本文件的差异。如下:
1) 磁盘中 Windows 文本文件总是以 "回车" + "换行"的形式进行换行的。
2) 磁盘中 Unix 格式的文本文件,总是以"换行符"(即:LF,'\n') 换行,而非 "回车换行符"。(Unix 规定:unix 文本文件保存到磁盘时,总是自动把 "回车换行符" 转换成 "回车符" 保存,输出到终端时由终端自动将将 "回车符" 转换成 "回车换行符" 输出) 

** 结论 1 **:这样在 windows 的记事本中打开 Unix 格式的文件时,因为文件中没有 '\r',所以无法正常显示换行,结果就会把所有的内容显示在同一行中。

** 结论 2 **:UtraEdit 等工具会自动检测文件中是否包含'\r',当检查行末缺少'\r'时,一般它会提示要求进行Unix 到Windows 格式的转换(相信都遇到这个提示信息)。

** 结论 3 **:UtraEdit 和 vi 等工具,在保存文件时会自动依照文件原来的格式进行保存。即:如打开的如是 windows 格式它会把文件依然按 windows 格式保存(不进行自动转换);如打开的如是unix 格式它会把文件依然按 unix 格式保存(不进行自动转换)。

下面是win2unix脚本,来自   http://www.google.com.hk/search?aq=f&sourceid=chrome&ie=UTF-8&q=win2unix

#!/usr/bin/perl -w 

use strict;
my $out;

if(@ARGV!=1 && @ARGV!=2){
print "Usage:\n\t$0 input [output];\n";
exit;
}

open(IN, "<$ARGV[0]") or die "couldn't open $ARGV[0]: $!";

if(<IN>=~m/(^#!.*perl.*)/){
$out.=$1;
}

while(<IN>){
chomp;
chop;
$_.="\n";
$out.=$_;
}

close IN;

if(@ARGV==1){
unlink $ARGV[0];
open(OUT,">$ARGV[0]") or die "couldn't open $ARGV[0]: $!";
}
elsif(@ARGV==2){
open(OUT,">$ARGV[1]") or die "couldn't open $ARGV[1]: $!";
}

print OUT $out;
close OUT;

参考:http://down.51cto.com/data/33367