cpp

#include <iostream>

#include <filesystem>

#include <string>

#include <vector>

#include <algorithm>

namespace fs = std::filesystem;

 

bool isImageFile(const std::string& ext)

{

    static const std::vector<std::string> imgExts = {

        ".jpg", ".jpeg", ".png", ".bmp", ".tif", ".tiff", ".webp"

    };

    std::string e = ext;

    std::transform(e.begin(), e.end(), e.begin(), ::tolower);

    return std::find(imgExts.begin(), imgExts.end(), e) != imgExts.end();

}

 

int main()

{

    std::string inputFolder = "D:/desk/picture/contrast_method/UIEB_test130";

    std::string outputFolder = "D:/桌面/新建文件夹";

    std::string keyword = "655";

 

    if (!fs::exists(inputFolder) || !fs::is_directory(inputFolder)) {

        std::cerr << "错误:输入文件夹不存在!" << std::endl;

        system("pause");

        return -1;

    }

 

    try {

        fs::create_directories(outputFolder);

    }

    catch (...) {

        std::cerr << "错误:无法创建输出文件夹!" << std::endl;

        system("pause");

        return -1;

    }

 

    int copiedCount = 0;

    for (const auto& methodEntry : fs::directory_iterator(inputFolder)) {

        if (!methodEntry.is_directory()) continue;

        std::string methodName = methodEntry.path().filename().string();

 

        for (const auto& fileEntry : fs::directory_iterator(methodEntry.path())) {

            if (!fileEntry.is_regular_file()) continue;

            std::string fileName = fileEntry.path().filename().string();

            std::string ext = fileEntry.path().extension().string();

 

            if (isImageFile(ext) && fileName.find(keyword) != std::string::npos) {

                fs::path targetDir = fs::path(outputFolder) / methodName;

                fs::create_directories(targetDir);

                fs::path targetFile = targetDir / fileName;

 

                try {

                    fs::copy_file(fileEntry.path(), targetFile, fs::copy_options::overwrite_existing);

                    std::cout << "已提取: " << methodName << " / " << fileName << std::endl;

                    copiedCount++;

                }

                catch (const std::exception& e) {

                    std::cerr << "复制失败: " << fileEntry.path() << " 原因: " << e.what() << std::endl;

                }

            }

        }

    }

 

    std::cout << "\n完成!共提取 " << copiedCount << " 张图片。" << std::endl;

    system("pause");

    return 0;

}

 

 

CSDN 完整发布文案(可直接复制)

 

标题:C++ std::filesystem 批量分层提取含指定关键字图片 | 多层文件夹自动分类复制

 

一、功能介绍

 

该程序用于多层嵌套图片文件夹批量筛选复制,适用于图像对比实验场景:

 

1. 根目录下存在多个子文件夹(不同算法/方法输出图片);

2. 遍历所有子文件夹,筛选文件名包含自定义关键字的图片;

3. 复制图片到输出目录,自动保留原文件夹分层结构;

4. 支持 jpg/png/tif/webp 等主流图片格式,后缀大小写兼容;

5. 异常捕获:文件夹不存在、创建失败、文件复制报错均有日志输出;

6. 重复文件自动覆盖,最终统计成功提取图片总数。

 

二、编译环境要求

 

1. C++17 标准( std::filesystem  依赖C++17,VS项目属性语言设置C++17)

2. Windows平台( system("pause")  控制台防闪退,Linux/Mac需删除该语句)

3. 无需OpenCV,纯标准库实现,轻量化无第三方图像库依赖

 

三、完整代码逐段解析

 

1. 头文件与命名空间

 

cpp

#include <iostream>

#include <filesystem>

#include <string>

#include <vector>

#include <algorithm>

namespace fs = std::filesystem;

 

 

-  filesystem :C++17标准文件系统库,实现文件夹遍历、文件复制、目录创建;

-  algorithm :提供 std::transform 、 std::find 用于后缀大小写转换与格式判断;

-  namespace fs = std::filesystem :简化文件系统代码书写。

 

2. 图片格式判断工具函数

 

cpp

bool isImageFile(const std::string& ext)

{

    static const std::vector<std::string> imgExts = {

        ".jpg", ".jpeg", ".png", ".bmp", ".tif", ".tiff", ".webp"

    };

    std::string e = ext;

    std::transform(e.begin(), e.end(), e.begin(), ::tolower);

    return std::find(imgExts.begin(), imgExts.end(), e) != imgExts.end();

}

 

 

- 内置支持7种常用图像后缀;

- 将文件后缀全部转为小写,兼容 .JPG 、 .PNG 大写后缀;

-  std::find 检索后缀是否在支持列表,返回布尔值判断是否为图片。

 

3. 核心配置区(仅需修改此处3个参数)

 

cpp

std::string inputFolder = "D:/desk/picture/contrast_method/UIEB_test130";

std::string outputFolder = "D:/桌面/新建文件夹";

std::string keyword = "655";

 

 

-  inputFolder :顶层根目录,内部存放多个分类子文件夹;

-  outputFolder :筛选后图片的输出总目录;

-  keyword :需要匹配的文件名关键字(如图片序号、类别标记)。

 

4. 输入文件夹合法性校验

 

cpp

if (!fs::exists(inputFolder) || !fs::is_directory(inputFolder)) {

    std::cerr << "错误:输入文件夹不存在!" << std::endl;

    system("pause");

    return -1;

}

 

 

判断输入路径是否存在且为文件夹,异常则提示并暂停控制台、退出程序。

 

5. 创建输出总目录(异常捕获)

 

cpp

try {

    fs::create_directories(outputFolder);

}

catch (...) {

    std::cerr << "错误:无法创建输出文件夹!" << std::endl;

    system("pause");

    return -1;

}

 

 

 create_directories 支持递归创建多级目录;使用try-catch捕获权限不足、路径非法等创建失败异常。

 

6. 外层循环:遍历根目录下所有分类子文件夹

 

cpp

int copiedCount = 0;

for (const auto& methodEntry : fs::directory_iterator(inputFolder)) {

    if (!methodEntry.is_directory()) continue;

    std::string methodName = methodEntry.path().filename().string();

 

 

 directory_iterator 迭代根目录下所有文件, is_directory() 过滤仅保留子文件夹;记录子文件夹名称用于还原输出分层。

 

7. 内层循环:遍历单个分类文件夹内所有文件

 

cpp

for (const auto& fileEntry : fs::directory_iterator(methodEntry.path())) {

    if (!fileEntry.is_regular_file()) continue;

    std::string fileName = fileEntry.path().filename().string();

    std::string ext = fileEntry.path().extension().string();

 

 

遍历子文件夹内部,过滤掉二级子目录,只处理图片等普通文件;提取文件名与文件后缀。

 

8. 筛选条件:图片 + 文件名包含关键字

 

cpp

if (isImageFile(ext) && fileName.find(keyword) != std::string::npos)

 

 

- 调用工具函数判断是否为图片;

-  string::find 查找关键字,返回 npos 代表无匹配,不满足则跳过当前文件。

 

9. 分层创建输出目录并复制文件

 

cpp

fs::path targetDir = fs::path(outputFolder) / methodName;

fs::create_directories(targetDir);

fs::path targetFile = targetDir / fileName;

 

try {

    fs::copy_file(fileEntry.path(), targetFile, fs::copy_options::overwrite_existing);

    std::cout << "已提取: " << methodName << " / " << fileName << std::endl;

    copiedCount++;

}

catch (const std::exception& e) {

    std::cerr << "复制失败: " << fileEntry.path() << " 原因: " << e.what() << std::endl;

}

 

 

1. 在输出目录下新建与原分类同名子文件夹,完美还原目录结构;

2.  copy_file 执行文件复制, overwrite_existing 开启覆盖旧文件;

3. try-catch捕获文件占用、权限不足等复制错误,打印失败路径与原因;

4. 成功复制则计数+1,并打印日志。

 

10. 程序收尾统计

 

cpp

std::cout << "\n完成!共提取 " << copiedCount << " 张图片。" << std::endl;

system("pause");

return 0;

 

 

循环结束后输出总提取图片数量; system("pause") 防止控制台运行结束直接闪退,方便查看日志。

 

四、使用场景

 

1. 图像复原/去雾/超分对比实验:多算法输出文件夹,批量提取同一编号测试图;

2. 数据集筛选:按标签序号提取指定样本;

3. 批量分类归档图片,自动保留原文件夹层级,无需手动新建分类目录。

 

五、跨平台适配修改

 

1. Linux / MacOS:删除所有 system("pause"); 语句;编译命令添加 -std=c++17 ;

2. 拓展图片格式:直接修改 imgExts 数组,追加 .heic 、 .raw 等后缀;

3. 改为移动文件:将 fs::copy_file 替换为 fs::rename 即可剪切而非复制。

 

六、项目配置要点

 

1. VS 项目属性 → C/C++ → 语言标准 → 选择  /std:c++17 ;

2. 字符集使用默认Unicode无影响,原生支持中文文件夹、中文文件名;

3. 无需链接任何第三方库,仅依赖C++标准库,编译轻量化。

 

七、程序优势

 

1. 纯标准库实现,无OpenCV等重型图像库依赖;

2. 自动保留原文件夹分层结构,整理实验图片更整洁;

3. 全路径中文兼容,支持带空格、特殊字符的文件夹名;

4. 完善异常捕获,快速定位损坏文件、权限问题;

5. 后缀大小写自动兼容,无需手动统一文件格式;

6. 可自定义关键字,灵活筛选目标图片。

更多推荐