LinuxEye - Linux系统教程

LinuxEye - Linux系统教程

当前位置: 主页 > 脚本编程 >

Linux下计算文件的MD5值

时间:2012-11-29 09:53来源:51cto 编辑:蝉翼飘渺 点击:
脚本功能 脚本使用Perl编写,计算文件的MD5值 脚本用途 服务器在安装完操作系统后,计算PATH变量里面所有的二进制文件的MD5、计算单个文件MD5值、计算某个目录(包括子目录)下所有的文件

脚本功能

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

脚本用途

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

脚本用法(5种用法)

脚本名 -p                   [ > 输出的文件名]  ← 该功能是计算PATH变量里面所有文件的MD5值 
脚本名 文件1 文件2 文件3 ...  [ > 输出的文件名]  ← 该功能是计算指定文件的MD5值 
脚本名 目录1 目录2 目录3 ...  [ > 输出的文件名]  ← 该功能是计算指定目录下所有文件的MD5值 
脚本名 -c MD5文件1 MD5文件2  [ > 输出的文件名]  ← 该功能是比较同一个目录下所有文件生成的2次MD5文件中有哪些MD5值不一致 
脚本名 目录 -f MD5文件       [ > 输出的文件名]  ← 该功能是跟上面的功能类似,只是这个不生成文件直接比对

注意事项

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

脚本内容

#!/usr/bin/perl
use Digest::MD5;
use File::Find;
 
# 2012-11-24 22:41 Leo chanyipiaomiao@163.com
# Blog:http://linux5588.blog.51cto.com
 
#用法提示 
$usage = "Usage: scriptname -p | Directory1 ... | File1 ... | -c MD5File1 MD5File2 | Directory -f MD5File [ > OUTFILE]"; 
$usagecompare = "Usage: scriptname -c MD5File1 MD5File2 [ > OUTFILE]"; 
$usagepath = "Usage: scriptname -p [ > OUTFILE]"; 
  
#判断命令行参数是否为空,为空 则直接计算PATH路径里面所有的二进制文件的MD5值,不为空  
#如果第一个参数是目录,那么调用getDirectoryAllFileMD5 计算目录里面所有文件的MD5值 
#如果第一个参数是文件,那么调用getSingleFileMD5 计算命令行参数里面所有文件的MD5值 
 if (@ARGV) { 
    my $arg = $ARGV[0]; 
    if (-d $arg ) { 
        if ($ARGV[1] eq '-f' && -T $ARGV[2]){ 
            &compareWithLastMD5File($arg);  
        } else { 
            &getDirectoryAllFileMD5(@ARGV); 
        } 
    } elsif ( -f $arg ) { 
        &getSingleFileMD5(@ARGV); 
    } elsif ($arg eq '-c' && @ARGV == 3 ) { 
        die "$usagecompare\n" unless (-T $ARGV[1] && -T $ARGV[2]); 
        &compareWithTwoMD5Files; 
    } elsif ($arg eq '-p') { 
        die "$usagepath\n" unless (@ARGV == 1); 
        &getPathBinFileMD5; 
    } else { 
        die "$usage\n"; 
    } 
 } else { 
    die "$usage\n"; 
 } 
  
#得到目录下所有文件(包括子目录)的MD5值 
 sub getDirectoryAllFileMD5 { 
    find(\&wantedPrint,@_); 
 } 
  
#得到PATH变量里面所有的二进制文件的MD5值 
 sub getPathBinFileMD5 { 
    my @path = split /:/,$ENV{PATH};  
    find(\&wantedPrint,@path); 
 } 
  
 #得到单个文件的MD5值 
 sub getSingleFileMD5 { 
    foreach (@_) { 
        if (-R $_) { 
            print "$_ ",&getMD5($_),"\n"; 
        } else { 
            print "Can't read $_\n"; 
            next; 
        } 
    } 
 } 
  
#先生成该目录下所有文件的MD5值,然后跟上一次该目录的生成的MD5文件对比 
#本次生成的MD5跟上一次生成的MD5文件比对,不一致的输出出来,同时将3个时间输出出来 
#如果是新添加的文件则输出出来其3个时间值,atime mtime ctime 
 sub compareWithLastMD5File { 
    find(\&wantedHash,@_); 
    my $md5file = $ARGV[2]; 
  
    open MD5FILE,"<","$md5file" or die "Can't read $md5file : $!\n"; 
    my $lastMD5Filerecords = (@lastMD5FilerecordsArray = <MD5FILE>); 
    my %lastMD5Hash = map { split } @lastMD5FilerecordsArray; 
    close MD5FILE; 
  
    foreach (keys %thisMD5Hash) { 
        $thisMD5Filerecords++; 
    } 
  
    if ($thisMD5Filerecords >= $lastMD5Filerecords) { 
        %hash1 = %thisMD5Hash; 
        %hash2 = %lastMD5Hash; 
    } else { 
        %hash1 = %lastMD5Hash; 
        %hash2 = %thisMD5Hash; 
    } 
  
    foreach  (keys %hash1) { 
        if (exists $hash2{$_}) { 
            if ( $hash1{$_} ne $hash2{$_} ) { 
                ($atime,$mtime,$ctime) = &getFileAMCTime($_); 
                print "Different:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n"; 
            } 
        } else { 
            if (-e $_) { 
                ($atime,$mtime,$ctime) = &getFileAMCTime($_); 
                print "Added:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n"; 
            } else { 
                print "Deleted:$_ $hash1{$_}\n"; 
            } 
        } 
    } 
 } 
  
#比较2个生成的MD5文件(对同一个目录生成的),找出不同的或者不存在的 
 sub compareWithTwoMD5Files { 
    my ($md5file1,$md5file2) = ($ARGV[1],$ARGV[2]); 
    open MD5FILE1,"<","$md5file1" or die "Can't read $md5file1 : $!\n"; 
    open MD5FILE2,"<","$md5file2" or die "Can't read $md5file2 : $!\n"; 
    my $file1record = (@file1record = <MD5FILE1>); 
    my $file2record = (@file2record = <MD5FILE2>); 
    close MD5FILE1; 
    close MD5FILE2; 
  
    my %hashmap1 = map { split } @file1record; 
    my %hashmap2 = map { split } @file2record; 
  
    if ($file1record >= $file2record) { 
        %hash1 = %hashmap1; 
        %hash2 = %hashmap2; 
    } else { 
        %hash1 = %hashmap2; 
        %hash2 = %hashmap1; 
    } 
  
    foreach  (keys %hash1) { 
        if (exists $hash2{$_}) { 
            if ( $hash1{$_} ne $hash2{$_} ) { 
                ($atime,$mtime,$ctime) = &getFileAMCTime($_); 
                print "Different:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n"; 
            } 
        } else { 
            if (-e $_) { 
                ($atime,$mtime,$ctime) = &getFileAMCTime($_); 
                print "Added:$_ $hash1{$_} Atime:$atime Mtime:$mtime Ctime:$ctime\n"; 
            } else { 
                print "Deleted:$_ $hash1{$_}\n"; 
            } 
        } 
    } 
 } 
  
#遍历条件,找到之后输出 
 sub wantedPrint { 
    if (-f $_ && -R $_) { 
        print "$File::Find::name  ",&getMD5($_),"\n"; 
    } 
 } 
  
#遍历条件,找到之后形成一个HASH 
 sub wantedHash { 
    if (-f $_ && -r $_) { 
        $thisMD5Hash{$File::Find::name} = &getMD5($_); 
    } 
 } 
  
#计算MD5值 
 sub getMD5 { 
    my $file = shift @_; 
    open(FH, $file) or die "Can't open '$file': $!\n"; 
    binmode(FH); 
    my $filemd5 = Digest::MD5->new->addfile(FH)->hexdigest; 
    close FH; 
    return $filemd5; 
 } 
  
#获取文件的atime,mtime,ctime 
 sub getFileAMCTime { 
    $filename = shift @_; 
    my ($atime,$mtime ,$ctime) = (stat ($filename))[8,9,10]; 
    $atime = &getTime($atime); 
    $mtime = &getTime($mtime); 
    $ctime = &getTime($ctime); 
  
    #将日期时间格式转换为比较友好的格式 
    sub getTime { 
        my $time = shift @_; 
        my($sec,$min,$hour,$day,$mon,$year) = (localtime $time)[0..5]; 
        $time = sprintf "%4d-%02d-%02d %2d:%02d:%02d",$year + 1900,$mon + 1,$day,$hour,$min,$sec; 
        return $time; 
    } 
    return $atime,$mtime,$ctime; 
 }

转载请保留固定链接: https://linuxeye.com/program/971.html

------分隔线----------------------------
标签:MD5
栏目列表
推荐内容