> CentOS > CentOS入门 >

Centos下计算文件的MD5值

脚本功能

脚本使用Perl编写,计算文件的MD5值

脚本用途

服务器在安装完操作系统后,计算PATH变量里面所有的二进制文件的MD5、计算单个文件MD5值、计算某个目录(包括子目录)下所有的文件的MD5值记录到文件,等日后再生成一份,然后2份文件进行对比,即可知道这些文件是否又被改动过.

脚本用法(6种用法)


  1. 脚本名 -p                   [ > 输出的文件名]  ← 该功能是计算PATH变量里面所有文件的MD5值

  2. 脚本名 -p -f MD5文件         [ > 输出的文件名]  ← 该功能是计算PATH变量里面所有文件的MD5值并跟上一次生成的MD5文件相对比

  3. 脚本名 文件1 文件2 文件3 ...  [ > 输出的文件名]  ← 该功能是计算指定文件的MD5值

  4. 脚本名 目录1 目录2 目录3 ...  [ > 输出的文件名]  ← 该功能是计算指定目录下所有文件的MD5值

  5. 脚本名 -c MD5文件1 MD5文件2  [ > 输出的文件名]   ← 该功能是比较同一个目录下所有文件生成的2次MD5文件中有哪些MD5值不一致

  6. 脚本名 目录 -f MD5文件       [ > 输出的文件名]  ← 该功能是跟上面的功能类似,只是这个不生成文件直接比对

注意事项

不能对/proc目录进行计算不能对/(根)进行计算,因为/里面包含/proc 不能对挂载在Linux上Windows的共享目录进行计算

脚本内容

【第二版】


  1. #!/usr/bin/perl  

  2. use Digest::MD5;

  3. use File::Find;

  4.  

  5. # 2012-12-16 15:24 Leo chanyipiaomiao@163.com

  6. # Blog:http://linux5588.blog.51cto.com

  7.  

  8. #用法提示

  9. $usage = "Usage: scriptname -p | Directory1 ... | File1 ... | -c MD5File1 MD5File2 | Directory -f MD5File [ > OUTFILE]";

  10. $usagecompare = "Usage: scriptname -c MD5File1 MD5File2 [ > OUTFILE]";

  11. $usagepath = "Usage: scriptname -p | -p -f MD5File [ > OUTFILE]";

  12.  

  13. #判断命令行参数是否为空,为空 则直接计算PATH路径里面所有的二进制文件的MD5值,不为空  

  14. #如果第一个参数是目录,那么调用getDirectoryAllFileMD5 计算目录里面所有文件的MD5值

  15. #如果第一个参数是文件,那么调用getSingleFileMD5 计算命令行参数里面所有文件的MD5值

  16. if (@ARGV) {

  17.    my $arg = $ARGV[0];

  18. if (-d $arg ) {

  19. if ($ARGV[1] eq '-f' && -T $ARGV[2]){

  20.            &compareWithLastMD5File($arg);  

  21.        } else {

  22.            &getDirectoryAllFileMD5(@ARGV);

  23.        }

  24.    } elsif ( -f $arg ) {

  25.        &getSingleFileMD5(@ARGV);

  26.    } elsif ($arg eq '-c' && @ARGV == 3 ) {

  27. die"$usagecompare\n" unless (-T $ARGV[1] && -T $ARGV[2]);

  28.        &compareWithTwoMD5Files;

  29.    } elsif ($arg eq '-p') {

  30. if (1 == @ARGV) {

  31.            &getPathBinFileMD5;

  32.        } elsif($ARGV[1] eq '-f' && -T $ARGV[2]) {

  33.            &compareWithLastPathMD5File;

  34.        } else {

  35. die"$usagepath\n";

  36.        }

  37.    } else {

  38. die"$usage\n";

  39.    }

  40. } else {

  41. die"$usage\n";

  42. }

  43.  

  44. #得到目录下所有文件(包括子目录)的MD5值

  45. sub getDirectoryAllFileMD5 {

  46.    find(\&wantedPrint,@_);

  47. }

  48.  

  49. #得到PATH变量里面所有的二进制文件的MD5值

  50. sub getPathBinFileMD5 {

  51.    my @path = split /:/,$ENV{PATH};  

  52.    find(\&wantedPrint,@path);

  53. }

  54.  

  55. #先得到本次PATH变量所有的目录下的文件的MD5值,然后对比以前是生成的MD5文件

  56. sub compareWithLastPathMD5File {

  57.    my @path = split /:/,$ENV{PATH};  

  58.    &compareWithLastMD5File(@path);

  59. }

  60.  

  61. #得到单个文件的MD5值

  62. sub getSingleFileMD5 {

  63. foreach (@_) {

  64. if (-R $_) {

  65.            print "$_ ",&getMD5($_),"\n";

  66.        } else {

  67.            print "Can't read $_\n";

  68.            next;

  69.        }

  70.    }

  71. }

  72.  

  73. #先生成该目录下所有文件的MD5值,然后跟上一次该目录的生成的MD5文件对比

  74. #本次生成的MD5跟上一次生成的MD5文件比对,不一致的输出出来,同时将3个时间输出出来

  75. #如果是新添加的文件则输出出来其3个时间值,atime mtime ctime

  76. sub compareWithLastMD5File {

  77.    find(\&wantedHash,@_);      #这里调用那个回调函数后就会生成一个%thisMD5Hash的哈希

  78.    my $md5file = $ARGV[2];

  79.  

  80.    open LASTMD5FILE,"<","$md5file"ordie"Can't read $md5file : $!\n";

  81.    my $lastMD5Filerecords = (@lastMD5FilerecordsArray = <LASTMD5FILE>);

  82.    %lastMD5Hash = map { split } @lastMD5FilerecordsArray;

  83.    close LASTMD5FILE;

  84.  

  85. foreach (keys %thisMD5Hash) {

  86. $thisMD5Filerecords++;

  87.    }

  88.    &compare($thisMD5Filerecords,$lastMD5Filerecords);

  89. }

  90.  

  91. #比较2个生成的MD5文件(对同一个目录生成的),找出不同的或者不存在的

  92. sub compareWithTwoMD5Files {

  93.    my ($md5file1,$md5file2) = ($ARGV[1],$ARGV[2]);

  94.    open MD5FILE1,"<","$md5file1"ordie"Can't read $md5file1 : $!\n";

  95.    open MD5FILE2,"<","$md5file2"ordie"Can't read $md5file2 : $!\n";

  96.    my $file1record = (@file1record = <MD5FILE1>);

  97.    my $file2record = (@file2record = <MD5FILE2>);

  98.    close MD5FILE1;

  99.    close MD5FILE2;

  100.  

  101.    %thisMD5Hash = map { split } @file1record;

  102.    %lastMD5Hash = map { split } @file2record;

  103.    &compare($file1record,$file2record);

  104. }

  105.  

  106. #对2个MD5文件进行比较或者是边生成边比对

  107. sub compare {

  108.    my($file1record,$file2record) = ($_[0],$_[1]);

  109.  

  110. if ($file1record >= $file2record) {

  111.        %hash1 = %thisMD5Hash;    

  112.        %hash2 = %lastMD5Hash;      

  113.    } else {

  114.        %hash1 = %lastMD5Hash;

  115.        %hash2 = %thisMD5Hash;

  116.    }

  117.  

  118.    my $count = 0;      

  119. foreach  (keys %hash1) {

  120. if (exists $hash2{$_}) {

  121. if ( $hash1{$_} ne $hash2{$_} ) {

  122. $count++;

  123.                ($atime,$mtime,$ctime) = &getFileAMCTime($_);

  124.                print "Different --> $_\n";

  125.                print "$hash2{$_}\n";

  126.                print "$hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n\n";

  127.            }

  128.        } else {

  129. $count++;

  130. if (-e $_) {

  131.                ($atime,$mtime,$ctime) = &getFileAMCTime($_);

  132.                print "Added --> $_ \n$hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n\n";

  133.            } else {

  134.                print "Deleted --> $_ $hash1{$_}\n\n";

  135.            }

  136.        }

  137.    }

  138. if ($count == 0) {

  139.        print "Not Found Different !!\n";

  140.    }

  141. }

  142.  

  143. #遍历条件,找到之后输出

  144. sub wantedPrint {

  145. if (-f $_ && -R $_) {

  146.        print "$File::Find::name  ",&getMD5($_),"\n";

  147.    }

  148. }

  149.  

  150. #遍历条件,找到之后形成一个HASH

  151. sub wantedHash {

  152. if (-f $_ && -r $_) {

  153. $thisMD5Hash{$File::Find::name} = &getMD5($_);

  154.    }

  155. }

  156.  

  157. #计算MD5值

  158. sub getMD5 {

  159.    my $file = shift @_;

  160.    open(FH, $file) ordie"Can't open '$file': $!\n";

  161.    binmode(FH);

  162.    my $filemd5 = Digest::MD5->new->addfile(FH)->hexdigest;

  163.    close FH;

  164. return$filemd5;

  165. }

  166.  

  167. #获取文件的atime,mtime,ctime

  168. sub getFileAMCTime {

  169. $filename = shift @_;

  170.    my ($atime,$mtime ,$ctime) = (stat ($filename))[8,9,10];

  171. $atime = &getTime($atime);

  172. $mtime = &getTime($mtime);

  173. $ctime = &getTime($ctime);

  174.  

  175.    #将日期时间格式转换为比较友好的格式

  176.    sub getTime {

  177.        my $time = shift @_;

  178.        my($sec,$min,$hour,$day,$mon,$year) = (localtime $time)[0..5];

  179. $time = sprintf "%4d-%02d-%02d %2d:%02d:%02d",$year + 1900,$mon + 1,$day,$hour,$min,$sec;

  180. return$time;

  181.    }

  182. return$atime,$mtime,$ctime;

  183. }

 

【第一版】


  1. #!/usr/bin/perl

  2. use Digest::MD5;

  3. use File::Find;

  4.  

  5. # 2012-11-24 22:41 Leo chanyipiaomiao@163.com

  6. # Blog:http://linux5588.blog.51cto.com

  7.  

  8. #用法提示

  9. $usage = "Usage: scriptname -p | Directory1 ... | File1 ... | -c MD5File1 MD5File2 | Directory -f MD5File [ > OUTFILE]";

  10. $usagecompare = "Usage: scriptname -c MD5File1 MD5File2 [ > OUTFILE]";

  11. $usagepath = "Usage: scriptname -p [ > OUTFILE]";

  12.  

  13. #判断命令行参数是否为空,为空 则直接计算PATH路径里面所有的二进制文件的MD5值,不为空  

  14. #如果第一个参数是目录,那么调用getDirectoryAllFileMD5 计算目录里面所有文件的MD5值

  15. #如果第一个参数是文件,那么调用getSingleFileMD5 计算命令行参数里面所有文件的MD5值

  16. if (@ARGV) {

  17.    my $arg = $ARGV[0];

  18.    if (-d $arg ) {

  19.        if ($ARGV[1] eq '-f' && -T $ARGV[2]){

  20.            &compareWithLastMD5File($arg);  

  21.        } else {

  22.            &getDirectoryAllFileMD5(@ARGV);

  23.        }

  24.    } elsif ( -f $arg ) {

  25.        &getSingleFileMD5(@ARGV);

  26.    } elsif ($arg eq '-c' && @ARGV == 3 ) {

  27.        die "$usagecompare\n" unless (-T $ARGV[1] && -T $ARGV[2]);

  28.        &compareWithTwoMD5Files;

  29.    } elsif ($arg eq '-p') {

  30.        die "$usagepath\n" unless (@ARGV == 1);

  31.        &getPathBinFileMD5;

  32.    } else {

  33.        die "$usage\n";

  34.    }

  35. } else {

  36.    die "$usage\n";

  37. }

  38.  

  39. #得到目录下所有文件(包括子目录)的MD5值

  40. sub getDirectoryAllFileMD5 {

  41.    find(\&wantedPrint,@_);

  42. }

  43.  

  44. #得到PATH变量里面所有的二进制文件的MD5值

  45. sub getPathBinFileMD5 {

  46.    my @path = split /:/,$ENV{PATH};  

  47.    find(\&wantedPrint,@path);

  48. }

  49.  

  50. #得到单个文件的MD5值

  51. sub getSingleFileMD5 {

  52.    foreach (@_) {

  53.        if (-R $_) {

  54.            print "$_ ",&getMD5($_),"\n";

  55.        } else {

  56.            print "Can't read $_\n";

  57. next;

  58.        }

  59.    }

  60. }

  61.  

  62. #先生成该目录下所有文件的MD5值,然后跟上一次该目录的生成的MD5文件对比

  63. #本次生成的MD5跟上一次生成的MD5文件比对,不一致的输出出来,同时将3个时间输出出来

  64. #如果是新添加的文件则输出出来其3个时间值,atime mtime ctime

  65. sub compareWithLastMD5File {

  66.    find(\&wantedHash,@_);

  67.    my $md5file = $ARGV[2];

  68.  

  69. open MD5FILE,"<","$md5file"or die "Can't read $md5file : $!\n";

  70.    my $lastMD5Filerecords = (@lastMD5FilerecordsArray = <MD5FILE>);

  71.    my %lastMD5Hash = map { split } @lastMD5FilerecordsArray;

  72. close MD5FILE;

  73.  

  74.    foreach (keys %thisMD5Hash) {

  75.        $thisMD5Filerecords++;

  76.    }

  77.  

  78.    if ($thisMD5Filerecords >= $lastMD5Filerecords) {

  79.        %hash1 = %thisMD5Hash;

  80.        %hash2 = %lastMD5Hash;

  81.    } else {

  82.        %hash1 = %lastMD5Hash;

  83.        %hash2 = %thisMD5Hash;

  84.    }

  85.  

  86.    foreach  (keys %hash1) {

  87.        if (exists $hash2{$_}) {

  88.            if ( $hash1{$_} ne $hash2{$_} ) {

  89.                ($atime,$mtime,$ctime) = &getFileAMCTime($_);

  90.                print "Different:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n";

  91.            }

  92.        } else {

  93.            if (-e $_) {

  94.                ($atime,$mtime,$ctime) = &getFileAMCTime($_);

  95.                print "Added:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n";

  96.            } else {

  97.                print "Deleted:$_ $hash1{$_}\n";

  98.            }

  99.        }

  100.    }

  101. }

  102.  

  103. #比较2个生成的MD5文件(对同一个目录生成的),找出不同的或者不存在的

  104. sub compareWithTwoMD5Files {

  105.    my ($md5file1,$md5file2) = ($ARGV[1],$ARGV[2]);

  106. open MD5FILE1,"<","$md5file1"or die "Can't read $md5file1 : $!\n";

  107. open MD5FILE2,"<","$md5file2"or die "Can't read $md5file2 : $!\n";

  108.    my $file1record = (@file1record = <MD5FILE1>);

  109.    my $file2record = (@file2record = <MD5FILE2>);

  110. close MD5FILE1;

  111. close MD5FILE2;

  112.  

  113.    my %hashmap1 = map { split } @file1record;

  114.    my %hashmap2 = map { split } @file2record;

  115.  

  116.    if ($file1record >= $file2record) {

  117.        %hash1 = %hashmap1;

  118.        %hash2 = %hashmap2;

  119.    } else {

  120.        %hash1 = %hashmap2;

  121.        %hash2 = %hashmap1;

  122.    }

  123.  

  124.    foreach  (keys %hash1) {

  125.        if (exists $hash2{$_}) {

  126.            if ( $hash1{$_} ne $hash2{$_} ) {

  127.                ($atime,$mtime,$ctime) = &getFileAMCTime($_);

  128.                print "Different:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n";

  129.            }

  130.        } else {

  131.            if (-e $_) {

  132.                ($atime,$mtime,$ctime) = &getFileAMCTime($_);

  133.                print "Added:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n";

  134.            } else {

  135.                print "Deleted:$_ $hash1{$_}\n";

  136.            }

  137.        }

  138.    }

  139. }

  140.  

  141. #遍历条件,找到之后输出

  142. sub wantedPrint {

  143.    if (-f $_ && -R $_) {

  144.        print "$File::Find::name  ",&getMD5($_),"\n";

  145.    }

  146. }

  147.  

  148. #遍历条件,找到之后形成一个HASH

  149. sub wantedHash {

  150.    if (-f $_ && -r $_) {

  151.        $thisMD5Hash{$File::Find::name} = &getMD5($_);

  152.    }

  153. }

  154.  

  155. #计算MD5值

  156. sub getMD5 {

  157.    my $file = shift @_;

  158. open(FH, $file) or die "Can't open '$file': $!\n";

  159.    binmode(FH);

  160.    my $filemd5 = Digest::MD5->new->addfile(FH)->hexdigest;

  161. close FH;

  162. return $filemd5;

  163. }

  164.  

  165. #获取文件的atime,mtime,ctime

  166. sub getFileAMCTime {

  167.    $filename = shift @_;

  168.    my ($atime,$mtime ,$ctime) = (stat ($filename))[8,9,10];

  169.    $atime = &getTime($atime);

  170.    $mtime = &getTime($mtime);

  171.    $ctime = &getTime($ctime);

  172.  

  173.    #将日期时间格式转换为比较友好的格式

  174.    sub getTime {

  175.        my $time = shift @_;

  176.        my($sec,$min,$hour,$day,$mon,$year) = (localtime $time)[0..5];

  177.        $time = sprintf "%4d-%02d-%02d %2d:%02d:%02d",$year + 1900,$mon + 1,$day,$hour,$min,$sec;

  178. return $time;

  179.    }

  180. return $atime,$mtime,$ctime;

  181. }

 

本文出自 “雷纳科斯的博客” 博客,请务必保留此出处http://linux5588.blog.51cto.com/65280/1070915

(责任编辑:IT)