Linux杂项:遍历指定目录计算文件的md5并输出到文件

目录

🍅点击这里查看所有博文

  随着自己工作的进行,接触到的技术栈也越来越多。给我一个很直观的感受就是,某一项技术/经验在刚开始接触的时候都记得很清楚。往往过了几个月都会忘记的差不多了,只有经常会用到的东西才有可能真正记下来。存在很多在特殊情况下有一点用处的技巧,用的不多的技巧可能一个星期就忘了。

  想了很久想通过一些手段把这些事情记录下来。也尝试过在书上记笔记,这也只是一时的,书不在手边的时候那些笔记就和没记一样,不是很方便。

  很多时候我们遇到了问题,一般情况下都是选择在搜索引擎检索相关内容,这样来的也更快一点,除非真的找不到才会去选择翻书。后来就想到了写博客,博客作为自己的一个笔记平台倒是挺合适的。随时可以查阅,不用随身携带。

  同时由于写博客是对外的,既然是对外的就不能随便写,任何人都可以看到。经验对于我来说那就只是经验而已,公布出来说不一定我的一些经验可以帮助到其他的人。遇到和我相同问题时可以少走一些弯路。

  既然决定了要写博客,那就只能认真去写。不管写的好不好,尽力就行。千里之行始于足下,一步一个脚印,慢慢来 ,写的多了慢慢也会变好的。权当是记录自己的成长的一个过程,等到以后再往回看时,就会发现自己以前原来这么菜😂。

  本系列博客所述资料均来自互联网,并不是本人原创(只有博客是自己写的)。出于热心,本人将自己的所学笔记整理并推出相对应的使用教程,方面其他人学习。为国内的物联网事业发展尽自己的一份绵薄之力,没有为自己谋取私利的想法。若出现侵权现象,请告知本人,本人会立即停止更新,并删除相应的文章和代码。

遍历排序目录

  代码片段中,对指定目录遍历。并存入到指定数组中,随后对文件名进行排序。按照顺序计算所有非空文件的md5值。

// 比较函数,用于排序
static int compare(const void *a, const void *b) {
    return strcmp(*(const char **)a, *(const char **)b);
}
static void dirfiles_md5sum(const char *dirname, const char *autofile) {
    DIR *dir;
    struct dirent *entry;
    int count = 0;
    char **files;
    
    dir = opendir(dirname);
    if (dir == NULL) {
        printf("Unable to open directory:%s", dirname);
        return;
    }
    // 统计目录中的文件和子目录数量
    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
            count++;
        }
    }
    // 分配内存
    files = (char **)malloc(count * sizeof(char *));
    if (files == NULL) {
        printf("malloc fail\n");
        closedir(dir);
        return;
    }
    // 重新遍历目录,并将文件名存储到数组中
    rewinddir(dir);
    count = 0;
    char path[128] = {0};
    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
            snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
            files[count] = strdup(path);
            count++;
        }
    }
    // 对文件名进行排序
    qsort(files, count, sizeof(char *), compare);
    // 遍历排序后的数组并输出文件名
    for (int i = 0; i < count; i++) {
        // 判断当前文件名是否为目录
        DIR *subdir = opendir(files[i]);
        if (subdir != NULL) {
            closedir(subdir);
            // 递归遍历子目录
            dirfiles_md5sum(files[i], autofile);
        }
        else
        {
            char *filename = files[i];
            FILE *file_handle = fopen(filename, "r");
            if (file_handle == NULL) {
                printf("Unable to open file:%s", filename);
                free(files[i]);
                continue;
            }
            // 读取一个字符,判断文件是否为空
            if (fgetc(file_handle) != EOF) {
                char md5sum[256] = {0};
                calculate_md5(filename, md5sum, sizeof(md5sum));
                append_line(autofile, md5sum);
            }
            fclose(file_handle);
        }
        free(files[i]);
    }
    // 释放内存并关闭目录
    free(files);
    closedir(dir);
}

遍历排序目录

  代码片段对传入的文件进行md5运算,并输出结果。通过popen调用系统命令md5sum用以计算md5值。该方法更简单一些,不需要移植open-ssl。

static int calculate_md5(const char *filename, char *md5sum, int md5sum_len) 
{
    FILE *fp = NULL;
    char check_md5_cmd[128] = { 0 };
    sprintf(check_md5_cmd, "md5sum %s", filename);
    fp = popen(check_md5_cmd, "r");
    if(!fp) {
        printf("md5sum calculation failed.");
        return -1;
    }
    if(NULL == fgets(md5sum, md5sum_len, fp)) {
        printf("can not get first md5sum");
        pclose(fp);
        return -1;
    }
    pclose(fp);
    printf("md5sum:%s",md5sum);
    return 0;
}

输出到指定目录

  以插入的方式(a)打开文件,直接写入即可。

static void append_line(const char *filename, const char *new_line) 
{    
    // 打开文件,以追加模式打开(如果文件不存在则创建)
    FILE *file = fopen(filename, "a");
    if (file == NULL) {
        printf("Unable to open file:%s", filename);
        return;
    }
    // 将新行写入文件
    fprintf(file, "%s", new_line);
    // 关闭文件
    fclose(file);
}

完整代码

#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>


#define FIREWARE_MODEM_MD5_FIEL "./md5sum.txt"

static void append_line(const char *filename, const char *new_line) 
{    
    // 打开文件,以追加模式打开(如果文件不存在则创建)
    FILE *file = fopen(filename, "a");
    if (file == NULL) {
        printf("Unable to open file:%s", filename);
        return;
    }
    // 将新行写入文件
    fprintf(file, "%s", new_line);
    // 关闭文件
    fclose(file);
}
static int calculate_md5(const char *filename, char *md5sum, int md5sum_len) 
{
    FILE *fp = NULL;
    char check_md5_cmd[128] = { 0 };
    sprintf(check_md5_cmd, "md5sum %s", filename);
    fp = popen(check_md5_cmd, "r");
    if(!fp) {
        printf("md5sum calculation failed.");
        return -1;
    }
    if(NULL == fgets(md5sum, md5sum_len, fp)) {
        printf("can not get first md5sum");
        pclose(fp);
        return -1;
    }
    pclose(fp);
    printf("md5sum:%s",md5sum);
    return 0;
}
// 比较函数,用于排序
static int compare(const void *a, const void *b) {
    return strcmp(*(const char **)a, *(const char **)b);
}
static void dirfiles_md5sum(const char *dirname, const char *autofile) {
    DIR *dir;
    struct dirent *entry;
    int count = 0;
    char **files;
    
    dir = opendir(dirname);
    if (dir == NULL) {
        printf("Unable to open directory:%s", dirname);
        return;
    }
    // 统计目录中的文件和子目录数量
    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
            count++;
        }
    }
    // 分配内存
    files = (char **)malloc(count * sizeof(char *));
    if (files == NULL) {
        printf("malloc fail\n");
        closedir(dir);
        return;
    }
    // 重新遍历目录,并将文件名存储到数组中
    rewinddir(dir);
    count = 0;
    char path[128] = {0};
    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
            snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
            files[count] = strdup(path);
            count++;
        }
    }
    // 对文件名进行排序
    qsort(files, count, sizeof(char *), compare);
    // 遍历排序后的数组并输出文件名
    for (int i = 0; i < count; i++) {
        // 判断当前文件名是否为目录
        DIR *subdir = opendir(files[i]);
        if (subdir != NULL) {
            closedir(subdir);
            // 递归遍历子目录
            dirfiles_md5sum(files[i], autofile);
        }
        else
        {
            char *filename = files[i];
            FILE *file_handle = fopen(filename, "r");
            if (file_handle == NULL) {
                printf("Unable to open file:%s", filename);
                free(files[i]);
                continue;
            }
            // 读取一个字符,判断文件是否为空
            if (fgetc(file_handle) != EOF) {
                char md5sum[256] = {0};
                calculate_md5(filename, md5sum, sizeof(md5sum));
                append_line(autofile, md5sum);
            }
            fclose(file_handle);
        }
        free(files[i]);
    }
    // 释放内存并关闭目录
    free(files);
    closedir(dir);
}

int main(void) {
    dirfiles_md5sum("./firmware",FIREWARE_MODEM_MD5_FIEL);
    return 0;
}

  那么本篇博客就到此结束了,这里只是记录了一些我个人的学习笔记,其中存在大量我自己的理解。文中所述不一定是完全正确的,可能有的地方我自己也理解错了。如果有些错的地方,欢迎大家批评指正。如有问题直接在对应的博客评论区指出即可,不需要私聊我。我们交流的内容留下来也有助于其他人查看,说不一定也有其他人遇到了同样的问题呢😂。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
文件操作合隐写是一种在CTF(Capture The Flag)比赛中常见的技巧。其中包括使用outguess解密文件信息、使用file命令来修改文件后缀名以正常打开文件,以及查找隐藏内容的方法。具体可以按以下步骤进行操作: 1. 使用outguess解密文件信息:outguess一般用于解密文件中隐藏的信息。首先,使用Stegdetect工具识别出是否是outguess加密的图片。如果是,则需要进行编译和安装outguess工具。通过运行"./configure & make & make install"命令来完成安装。然后,可以使用outguess命令来解密文件,格式为"outguess -r 要解密的文件输出结果文件名"。 2. 使用file命令修改文件后缀名:当一个文件没有后缀名或者有后缀名但无法正常打开时,可以使用file命令来识别文件类型,并根据识别出的文件类型来修改文件后缀名。使用命令"file 文件名"来获取文件类型信息,然后根据文件类型修改后缀名即可正常打开文件。 3. 查找隐藏内容:在文件中隐藏内容的常见方法是直接将密钥以十六进制的形式写在文件的开头或结尾部分。在分析文件时,可以重点观察文件的开头和结尾部分。如果密钥在文件中间部分隐藏,则可以通过搜索关键字KEY或flag来查找隐藏内容。在Windows下,可以使用工具如Winhex或010Editor来搜索隐写的文件内容。 综上所述,CTF杂项文件操作合隐写涉及outguess解密文件信息、使用file命令修改文件后缀名以正常打开文件,以及查找隐藏内容的方法。以上是一些常见操作步骤,具体情况可能会有所不同。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

遇雪长安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值