You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将多文件夹中的JPG图片合并复制到单个文件夹的技术需求

批量复制嵌套文件夹中JPG图片到目标文件夹的C语言实现

嘿,我看你已经着手写C代码处理嵌套文件夹里的JPG批量复制了,刚好我之前做过类似需求,给你完善好完整的可运行实现,还会拆解关键逻辑,方便你理解~

#include <stdio.h>
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

// 复制单个文件的核心函数
int copy_file(const char *src_path, const char *dest_path) {
    FILE *src = fopen(src_path, "rb");
    if (!src) {
        perror("无法打开源文件");
        return -1;
    }

    FILE *dest = fopen(dest_path, "wb");
    if (!dest) {
        perror("无法打开目标文件");
        fclose(src);
        return -1;
    }

    // 用4KB缓冲区提升读写效率
    char buffer[4096];
    size_t bytes_read;
    while ((bytes_read = fread(buffer, 1, sizeof(buffer), src)) > 0) {
        if (fwrite(buffer, 1, bytes_read, dest) != bytes_read) {
            perror("写入目标文件失败");
            fclose(src);
            fclose(dest);
            return -1;
        }
    }

    if (ferror(src)) {
        perror("读取源文件失败");
        fclose(src);
        fclose(dest);
        return -1;
    }

    fclose(src);
    fclose(dest);
    return 0;
}

// 递归遍历目录,处理所有子文件夹
void traverse_directory(const char *dir_path, const char *dest_dir) {
    DIR *dir = opendir(dir_path);
    if (!dir) {
        perror("无法打开目录");
        return;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        // 跳过当前目录(.)和上级目录(..),避免无限递归
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }

        // 拼接当前文件/子目录的完整路径
        char full_path[1024];
        snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, entry->d_name);

        // 获取文件属性,区分目录和普通文件
        struct stat stat_buf;
        if (stat(full_path, &stat_buf) == -1) {
            perror("获取文件属性失败");
            continue;
        }

        if (S_ISDIR(stat_buf.st_mode)) {
            // 如果是子目录,递归进去继续处理
            traverse_directory(full_path, dest_dir);
        } else {
            // 检查是否是JPG文件(兼容大小写后缀)
            char *ext = strrchr(entry->d_name, '.');
            if (ext != NULL && (strcmp(ext, ".jpg") == 0 || strcmp(ext, ".JPG") == 0)) {
                // 处理文件名重复:自动添加数字后缀避免覆盖
                char dest_path[1024];
                int suffix = 0;
                while (1) {
                    if (suffix == 0) {
                        snprintf(dest_path, sizeof(dest_path), "%s/%s", dest_dir, entry->d_name);
                    } else {
                        char base_name[512];
                        strncpy(base_name, entry->d_name, ext - entry->d_name);
                        base_name[ext - entry->d_name] = '\0';
                        snprintf(dest_path, sizeof(dest_path), "%s/%s_%d.jpg", dest_dir, base_name, suffix);
                    }

                    // 检查目标文件是否存在,不存在就用这个路径
                    if (access(dest_path, F_OK) == -1) {
                        break;
                    }
                    suffix++;
                }

                // 执行复制并打印日志
                if (copy_file(full_path, dest_path) == 0) {
                    printf("已复制: %s -> %s\n", full_path, dest_path);
                }
            }
        }
    }

    closedir(dir);
}

// 确保目标文件夹存在,不存在则创建
int create_directory(const char *dir_path) {
    struct stat stat_buf;
    if (stat(dir_path, &stat_buf) == -1) {
        // 目录不存在,创建它(权限设为0755,通用可读可执行)
        if (mkdir(dir_path, 0755) == -1) {
            perror("创建目标文件夹失败");
            return -1;
        }
    } else if (!S_ISDIR(stat_buf.st_mode)) {
        fprintf(stderr, "错误:%s 不是一个目录\n", dir_path);
        return -1;
    }
    return 0;
}

int main(int argc, char *argv[]) {
    // 检查命令行参数是否正确
    if (argc != 3) {
        fprintf(stderr, "使用方法:%s <源父文件夹路径> <目标文件夹路径>\n", argv[0]);
        return EXIT_FAILURE;
    }

    const char *src_dir = argv[1];
    const char *dest_dir = argv[2];

    // 先创建目标文件夹(如果需要)
    if (create_directory(dest_dir) == -1) {
        return EXIT_FAILURE;
    }

    // 开始遍历源目录处理所有JPG
    traverse_directory(src_dir, dest_dir);

    printf("复制完成!\n");
    return EXIT_SUCCESS;
}

关键逻辑说明

  • 递归目录遍历:traverse_directory函数会自动进入每个子文件夹,跳过特殊目录避免死循环;
  • 高效文件复制:用4KB缓冲区读写,比单字节读写效率提升明显;
  • 重复文件名处理:自动添加_1、_2这类后缀,不用担心覆盖目标文件夹里的原有文件;
  • 兼容性处理:同时识别.jpg和.JPG后缀,你可以自行添加.jpeg等其他格式的判断;
  • 错误处理:每一步操作都加了错误提示,方便排查问题。

使用方法

  1. 编译代码:
gcc -o copy_jpgs copy_jpgs.c
  1. 运行程序(替换成你的实际路径):
./copy_jpgs ./2018 ./all_jpgs

内容的提问来源于stack exchange,提问作者AHF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:18:33