使用C++遍历打印C盘所有文件路径时的权限问题求助
如何遍历C盘所有文件路径并处理权限问题
我尝试打印C盘中的所有文件路径,但遇到了权限错误。以下是我的实现代码:
void getAllFilesInDirectory(wstring directoryPath, vector<wstring> &files) { for (filesystem::directory_entry directory : filesystem::directory_iterator(directoryPath)) { if (GetFileAttributesW(directory.path().wstring().c_str()) == FILE_ATTRIBUTE_SYSTEM) continue; //Checking if directory.path is a file or a directory if (GetFileAttributesW(directory.path().wstring().c_str()) == FILE_ATTRIBUTE_NORMAL) { files.push_back(directory.path().wstring()); wcout << "The path is " << directory.path().wstring() << endl; continue; } try { for (filesystem::directory_entry file : filesystem::recursive_directory_iterator(directory)) { if (GetFileAttributesW(file.path().wstring().c_str()) == FILE_ATTRIBUTE_DIRECTORY) { continue; } wcout << "The path of the file is " << file.path().wstring() << endl; files.push_back(file.path().wstring()); } } catch (exception &e) { wcout << "There is exception " << e.what() << " and the directory path is: " << directory.path().wstring() << endl; } } }该代码在遍历普通无权限限制的目录时可正常工作,但当传入路径为"C:"时,仅打印少量文件路径后就停止运行。希望有人能提供一种可以完整打印C盘所有文件路径的实现方法,感谢!
问题分析
你的代码遇到的核心问题有几个:
- 权限处理不彻底:
recursive_directory_iterator在构造时如果遇到无权限的目录会直接抛出异常,而你的catch块只能捕获一次,之后整个外层循环可能因为未处理的异常终止,导致后续目录没被遍历。 - 文件属性判断不准确:用
GetFileAttributesW判断FILE_ATTRIBUTE_NORMAL会漏掉很多非普通属性的文件(比如只读、隐藏文件),而且重复调用该函数效率很低。 - 未处理重解析点:C盘存在很多符号链接或快捷方式(重解析点),直接递归可能导致无限循环或访问无效路径。
解决方案
要完整遍历C盘,你需要做到以下几点:
- 以管理员身份运行程序:这是硬性要求,C盘的系统目录(如
C:\Windows\System32、C:\Program Files下的部分子目录)只有管理员权限才能访问。 - 逐个处理目录条目,避免批量构造迭代器:不要直接构造
recursive_directory_iterator,而是手动递归,遇到权限问题时跳过当前目录,继续处理其他目录。 - 使用filesystem库的原生判断函数:用
is_regular_file、is_directory、is_symlink等函数替代GetFileAttributesW,更可靠且代码更简洁。 - 捕获特定的filesystem异常:
std::filesystem抛出的是filesystem_error,而非普通的exception,需要针对性捕获。
改进后的代码
#include <iostream> #include <vector> #include <filesystem> #include <windows.h> namespace fs = std::filesystem; void getAllFilesInDirectory(const fs::path& directoryPath, std::vector<fs::path>& files) { try { // 遍历当前目录下的所有条目 for (const auto& entry : fs::directory_iterator(directoryPath)) { try { // 跳过符号链接(避免循环和访问无效路径) if (fs::is_symlink(entry)) { continue; } // 如果是普通文件,加入列表并打印 if (fs::is_regular_file(entry)) { files.push_back(entry.path()); std::wcout << L"文件路径: " << entry.path().wstring() << std::endl; } // 如果是目录,递归遍历 else if (fs::is_directory(entry)) { // 跳过系统目录(可选,根据需求调整) DWORD attrs = GetFileAttributesW(entry.path().c_str()); if ((attrs & FILE_ATTRIBUTE_SYSTEM) != 0) { continue; } getAllFilesInDirectory(entry.path(), files); } } catch (const fs::filesystem_error& e) { // 处理单个条目访问失败(比如权限不足) std::wcout << L"访问失败: " << entry.path().wstring() << L",错误信息: " << e.what() << std::endl; continue; // 跳过当前条目,继续处理其他 } } } catch (const fs::filesystem_error& e) { std::wcout << L"目录访问失败: " << directoryPath.wstring() << L",错误信息: " << e.what() << std::endl; } } int main() { std::vector<fs::path> allFiles; getAllFilesInDirectory(L"C:\\", allFiles); std::wcout << L"总共找到 " << allFiles.size() << L" 个文件" << std::endl; return 0; }
额外说明
- 管理员权限:右键点击编译后的exe,选择"以管理员身份运行",否则很多系统目录会被跳过。
- 跳过系统目录:代码中保留了跳过系统目录的逻辑,如果需要遍历系统目录,可以注释掉这部分代码,但即使有管理员权限,某些系统目录(如
C:\Windows\WinSxS下的部分文件)仍然可能无法访问,这是Windows的安全机制限制。 - 性能优化:遍历C盘会产生大量IO操作,速度可能较慢,建议不要在遍历过程中频繁打印,而是先收集所有路径,最后统一处理。
内容的提问来源于stack exchange,提问作者tantan
相关产品推荐
相关产品推荐

