C++ std::filesystem 批量分层提取含指定关键字图片 | 多层文件夹自动分类复制
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. 可自定义关键字,灵活筛选目标图片。
更多推荐
所有评论(0)