上一篇博客已经介绍了boost库,那现在就直接上强度!
先来讲解一下思路:
fs::remove_all()不能保证删除干净,它会在第一次发生错误时退出。
因此用remove+directory_interator类遍历目录。
第二个问题是错误处理
,try的效率低而且无法加工错误信息,因此这里用error_code。
bool Remove(fs::path rmPath) {
boost::system::error_code errorCode;
bool isDir = fs::is_directory(rmPath, errorCode);
if (errorCode)
PutError(rmPath.string() + " - " + errorCode.message());
if (isDir) {
fs::directory_iterator dirIterator(rmPath, errorCode);
if (errorCode)
PutError(rmPath.string() + " - " + errorCode.message());
for (fs::directory_entry entry : dirIterator) {
fs::path path(entry.path());
bool isDir = fs::is_directory(path, errorCode);
if (errorCode)
PutError(path.string() + " - " + errorCode.message());
if (isDir) {
if (mode_s)
Remove(path);
} else
Remove(path);
}
fs::remove(rmPath, errorCode);
if (errorCode)
return PutError(rmPath.string() + " - " + errorCode.message()), false;
else
return PutMessage("已删除文件夹:" + rmPath.string()), true;
} else {
fs::remove(rmPath, errorCode);
if (errorCode)
return PutError(rmPath.string() + " - " + errorCode.message()), false;
else
return PutMessage("已删除文件: " + rmPath.string()), true;
}
}
这是主体代码,Remove()函数。
error_code.message()只返回“拒绝访问”这种简短的报告,不像catch那样粗鲁:
boost::filesystem::remove()::拒绝访问,那岂不暴露是boost了吗?
Remove函数就这样递归删除,return true表示删干净了,否则就有错误。
接下来是完整代码
/**
* @file rmdir.cpp
* @brief 递归删除文件和目录的工具
* @author Liu-Yuze
* @date 2025
* @license Boost Software License 1.0
*/
#include <boost/filesystem.hpp>
#include <iostream>
#include <vector>
namespace fs = boost::filesystem;
int Options = 0;
enum Option {
RECURSIVE = 0x1,
QUIET = 0x2,
SUPPRESS_ERROR = 0x4,
};
void PutError(const std::string& errorMessage) {
if (!(Options & SUPPRESS_ERROR))
std::cerr << errorMessage << '\n';
}
void PutMessage(const std::string& message) {
if (!(Options & QUIET))
std::cout << message << '\n';
}
//主函数,可以删除目录和文件,返回0则没删干净。
bool Remove(fs::path rmPath) {
//error_code一个就够。
boost::system::error_code errorCode;
bool isDir = fs::is_directory(rmPath, errorCode);
if (errorCode)
PutError(rmPath.string() + " - " + errorCode.message());
//如果是文件夹,递归删除子文件夹和文件,再删除自己。
if (isDir) {
//文件夹迭代器,解析文件夹内容。
fs::directory_iterator dirIterator(rmPath, errorCode);
if (errorCode)
PutError(rmPath.string() + " - " + errorCode.message());
//遍历子文件夹和文件。
for (fs::directory_entry entry : dirIterator) {
fs::path path(entry.path());
bool isDir = fs::is_directory(path, errorCode);
if (errorCode)
PutError(path.string() + " - " + errorCode.message());
//是文件夹而且递归删除模式开启。
if (isDir) {
if (Options & RECURSIVE)
Remove(path);
}
//是文件直接删。
else
Remove(path);
}
//这是删除文件部分,删掉了就返回true,否则就是文件夹里有文件。
fs::remove(rmPath, errorCode);
if (errorCode)
return PutError(rmPath.string() + " - " + errorCode.message()), false;
else
return PutMessage("已删除文件夹:" + rmPath.string()), true;
}
else {
//这是删除文件部分,删掉了就返回true.
fs::remove(rmPath, errorCode);
if (errorCode)
return PutError(rmPath.string() + " - " + errorCode.message()), false;
else
return PutMessage("已删除文件: " + rmPath.string()), true;
}
}
void ShowHelp() {
PutMessage(
"Usage: rmdir [Options] <path1> <path2> ...\n"
"Options:\n"
" -recursive 递归删除目录\n"
" -quiet 抑制删除信息\n"
" --suppress-errors 抑制错误信息\n"
" --help/-? 显示帮助信息"
);
}
int main(int argc, char* argv[]) {
try {//std的函数有点多,以防万一吧!
//没有用到cstdio,那stdio就牺牲一下吧!
std::ios::sync_with_stdio(false);
boost::system::error_code error_code;
//至少要个运行路径和删除目录吧。
if (argc < 2) {
PutError("Usage: rmdir [Options] <path1> <path2> ...");
return 0;
}
//要删除的目录在这里。
std::vector<fs::path> pathToRemove;
for (int i = 1; i < argc; ++i) {
try {
std::string arg = argv[i];
//fs::absolute(fs::path)函数是处理斜杠的。
fs::path path = fs::absolute(arg, error_code);
if (error_code)
PutError(arg + " - " + error_code.message());
//判断路径存不存在,存在就把完整路径丢给pathToRemove的构造函数,
//也就是fs::canonical(fs::path)函数,它会处理"./../"之类的。
if (fs::exists(path)) {
pathToRemove.emplace_back(fs::canonical(path, error_code));
if (error_code)
PutError(error_code.message());
}
//不知道的看ShowHelp()函数。
else if (arg == "--help" || arg == "-?") {
ShowHelp();
return 0;
}
else if (arg == "-recursive")
Options |= RECURSIVE;
else if (arg == "-quiet")
Options |= QUIET;
else if (arg == "--suppress-errors")
Options |= SUPPRESS_ERROR;
else
PutError("没有路径或选项:" + arg);
}
catch (const fs::filesystem_error& e) {
PutError(e.what());
}
}
//一堆选项却没路径。
if (pathToRemove.empty()) {
PutError("请指定有效路径!");
return 2;
}
bool isRemove = true;
for (const auto& path : pathToRemove)
isRemove &= Remove(path);
//删干净了返回0,否则返回1。
return (isRemove) ? 0 : 1;
}
catch (std::exception& e) {
PutError(e.what());
return 3;
}
}
一个简单的rmdir就是这么简单。