编写原因

当初编写这个小工具的原因是,当解压某个压缩包到指定目录时,覆盖时会将目标目录里面的文件损坏,这个工具可以校验压缩包里面的文件有没有全部正确无损的覆盖到目标路径。

工具分为shell脚本和C语言两个部分。

原理说明

在打包压缩文件前,运行md5.sh脚本(也就是下面的脚本)。使用前先用chmod+x增加可执行权限,这个脚本会递归的将当前目录内的所有文件的文件名和对应的md5值记录到名为check.md5文件中。

在解压该压缩包后,运行md5_check程序(由下面C代码编译生成)时,会依次计算check.md5里所有文件的md5值,与表中记录的正确的md5值进行对比,通过比较md5值的一致性判断文件有无正确覆盖,而且会将校验结果输出到指定文件。

Shell脚本

#!/bin/bash 
# program:
# Calculate the MD5 value of all files in the current folder.
# History:
# 2016/10/28 Shang Yexin First release
function ergodic(){ 
    for file in ` ls -a $1 ` 
    do 
        if [ $file == . ] || [ $file == .. ]
        then 
            continue
        fi
        if [ -d $1/$file ] 
        then 
            ergodic $1/$file 
        else 
            md5sum $1/$file | sed s#$INIT_PATH/## >> $RECORDFILE
        fi 
    done 
}
#设置输出文件名
RECORDFILE=check.md5
#如果存在先删除,防止重复运行脚本时追加到记录文件
test -e $RECORDFILE && rm $RECORDFILE
#获取当前目录
INIT_PATH=`pwd`
#遍历所有文件
ergodic $INIT_PATH
#删除不需要的隐藏文件
sed -i / \./d $RECORDFILE
#按文件名称排序
sort t -k 2 $RECORDFILE -o $RECORDFILE

C语言

源码地址:https://github.com/shangyexin/md5sum

下载源码:

git clone https://github.com/shangyexin/md5sum.git

部分源码:

/**
 * 校验文件md5值,查询列表中所有文件与记录的MD5值是否匹配
 * @param md5list   文件MD5值列表
 * @param rootpath  根文件系统路径
 * @return 校验完成返回0,错误失败返回-1
*/
int md5_check_list(const char *md5list,const char *rootpath)
{
    int ret = 0;
    int fd_md5;
    int count_success = 0;
    int count_fail = 0;
    FILE *listFile;
    char md5_correct[MD5_LENTH+1] = {0};
    char filename[PATH_LENTH] = {0};
    char entryname[PATH_LENTH] = {0};
    char record_file[PATH_LENTH] = {0};
    char check_success_msg[MSG_LENTH] = {0};
    char check_failed_msg[MSG_LENTH] = {0};
    const char* note = "md5 check failed files:\n";//提示信息
    const char* none_msg = "[File not exist]  ";//文件不存在提示信息
    const char* wrong_msg = "[Md5  not match]  ";//文件md5不匹配提示信息

    /*打开待校验列表文件*/
    listFile = fopen(md5list,"r");
    if(NULL == listFile){
        printf("[md5_check] Open %s failed!\n",md5list);
        return -1;
    }
    /*创建结果记录文件*/
    if( NULL != get_current_time() ) {
        sprintf(record_file,"%s%s%s%s",RECORD_FILE_PATH,RECORD_FILE_PREFIX,get_current_time(),".log");
    }else {
        sprintf(record_file,"%s%s%s%s",RECORD_FILE_PATH,RECORD_FILE_PREFIX,"timenull",".log");
    }
    fd_md5 = open(record_file,O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
    if( fd_md5 > 0 ){
        /*写入提示信息*/
        write(fd_md5,note,strlen(note));
        write(fd_md5,"\n",1);
    } else {
        printf("[md5_check] Open %s failed! md5 check quit-----------------\n",record_file);
        return -1;
    }
    /*获取正确的md5值*/
    while( fscanf(listFile,"%s",md5_correct) != EOF ){
        /*获取文件名*/
        fscanf(listFile,"%s",entryname );
        /*拼接文件名*/
        if (rootpath == NULL) {
            snprintf(filename, PATH_LENTH, "%s%s", DEFAULT_ROOT_PATH, entryname);
        }
        else {
            snprintf(filename, PATH_LENTH, "%s%s", rootpath, entryname);
        }
        /*检验传入的文件名是否为普通文件,不是的话不校验*/
        ret = is_file(filename);
        if( -1 == ret ){
            write(fd_md5,none_msg,strlen(none_msg));
            write(fd_md5,filename,strlen(filename));
            write(fd_md5,"\n",1);
            count_fail ++;
            continue;
        }else if( 1 == ret ) {
            continue;
        }
        /*校验文件的MD5并与列表中正确的MD5进行比较,一致校验通过,否则失败*/
        if( 0 == strncmp(md5_correct,md5_check(filename),MD5_LENTH) ) {
            //printf("%s md5 check success!\n",filename);
            count_success ++;
        }
        else {
            //printf("%s md5 check failed!\n",filename);
            /*向文件中记录md5校验失败的文件*/
            write(fd_md5,wrong_msg,strlen(none_msg));
            write(fd_md5,filename,strlen(filename));
            write(fd_md5,"\n",1);
            count_fail ++;
        }
    }
    write(fd_md5,"\n",1);
    sprintf(check_failed_msg,"%d%s",count_fail," files update failed!");
    write(fd_md5,check_failed_msg,strlen(check_failed_msg));
    write(fd_md5,"\n",1);
    sprintf(check_success_msg,"%d%s",count_success," files update success!");
    write(fd_md5,check_success_msg,strlen(check_success_msg));
    write(fd_md5,"\n",1);
    close(fd_md5);

    return 0;
}
linux下递归计算当前文件夹所有文件MD5值shell脚本
Tagged on:     

One thought on “linux下递归计算当前文件夹所有文件MD5值shell脚本

发表评论

电子邮件地址不会被公开。 必填项已用*标注