同一DIR命令在CMD与Visual Studio中执行异常的解决咨询
解决Visual Studio中调用system执行dir命令提示"File Not Found"及获取所有文件路径的问题
咱们一步步拆解你遇到的问题,逐个击破:
1. 先搞定最直接的路径问题
你的path_to_check末尾多了一个空格:"C:\\Windows\\System32\\00tobedeleted ",这会让CMD误以为要找带空格后缀的文件夹,但实际你的文件夹是00tobedeleted——这大概率是触发"File Not Found"的直接原因。
另外,哪怕路径现在没空格,拼接CMD命令时也必须给路径套双引号(否则以后路径含空格时直接报错)。修正后的命令拼接应该是这样:
string cmd = "dir \"" + path_to_check + "\" /s /b /a > \"" + path_to_save + "filepaths.txt\""; system(cmd.c_str());
这里加的/a参数是让dir显示所有属性的文件(包括隐藏、系统文件),刚好满足你要获取所有文件的需求。
2. 处理System32的文件系统重定向坑
如果你的Visual Studio项目是32位的,在64位Windows系统上,程序访问C:\Windows\System32会被自动重定向到C:\Windows\SysWOW64——而你的00tobedeleted文件夹是在真实的System32里,所以32位程序根本找不到它。
解决办法二选一:
- 把项目改成64位:在VS解决方案资源管理器右键项目→属性→配置属性→常规→平台工具集,选择x64后重新编译;
- 必须用32位程序的话,调用Windows API关闭重定向:
#include <Windows.h> void Database::set_files_checksum(string path_to_check, string path_to_save) { PVOID oldValue = nullptr; // 关闭64位文件系统重定向 Wow64DisableWow64FsRedirection(&oldValue); string cmd = "dir \"" + path_to_check + "\" /s /b /a > \"" + path_to_save + "filepaths.txt\""; system(cmd.c_str()); // 用完恢复重定向 Wow64RevertWow64FsRedirection(oldValue); }
3. 更可靠的替代方案:抛弃system,用原生API
调用system()依赖CMD.exe,容易受环境变量、权限、路径解析等问题影响。推荐用更可控的方式获取文件路径:
方案A:C++17 filesystem库(推荐)
这是标准库的一部分,跨平台且代码简洁:
#include "database.h" #include <filesystem> #include <fstream> #include <string> namespace fs = std::filesystem; using namespace std; void Database::set_files_checksum(const string& path_to_check, const string& path_to_save) { ofstream out_file(path_to_save + "filepaths.txt"); if (!out_file.is_open()) { // 处理文件打开失败的情况,比如权限不足 return; } // 递归遍历目录,跳过权限不足的文件夹,获取所有常规文件(含隐藏) for (const auto& entry : fs::recursive_directory_iterator( path_to_check, fs::directory_options::skip_permission_denied | fs::directory_options::follow_directory_symlinks)) { if (fs::is_regular_file(entry)) { out_file << entry.path().string() << '\n'; } } }
注意:需要在VS项目属性里开启C++17或更高版本,或者添加/std:c++17编译选项。
方案B:Windows原生FindFirstFile/FindNextFile API
如果要兼容C++17之前的版本,或者更精细控制文件属性,可以用Windows原生API:
#include "database.h" #include <Windows.h> #include <fstream> #include <string> using namespace std; void traverse_directory(const string& dir_path, ofstream& out_file) { string search_path = dir_path + "\\*"; WIN32_FIND_DATA find_data; HANDLE hFind = FindFirstFile(search_path.c_str(), &find_data); if (hFind == INVALID_HANDLE_VALUE) { return; } do { // 跳过.和..目录 if (strcmp(find_data.cFileName, ".") == 0 || strcmp(find_data.cFileName, "..") == 0) { continue; } string full_path = dir_path + "\\" + find_data.cFileName; // 如果是目录,递归遍历 if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { traverse_directory(full_path, out_file); } else { // 写入所有类型的文件路径(含隐藏、系统文件) out_file << full_path << '\n'; } } while (FindNextFile(hFind, &find_data)); FindClose(hFind); } void Database::set_files_checksum(string path_to_check, string path_to_save) { ofstream out_file(path_to_save + "filepaths.txt"); if (!out_file.is_open()) { return; } traverse_directory(path_to_check, out_file); }
总结
- 先去掉
path_to_check末尾的多余空格,给路径套双引号,加上/a参数获取所有文件; - 如果是32位程序,要么改成64位,要么关闭文件系统重定向;
- 长期来看,用C++标准库或Windows原生API替代
system(),能避免很多依赖CMD的坑。
内容的提问来源于stack exchange,提问作者Ironwing
相关产品推荐
相关产品推荐

