C ++递归搜索具有某些扩展名的文件

Posted

技术标签:

【中文标题】C ++递归搜索具有某些扩展名的文件【英文标题】:C++ Recursively searching for files with certain extensions 【发布时间】:2019-10-25 10:28:18 【问题描述】:

我正在尝试编写一个函数来获取文件扩展名的std::set,并递归搜索具有这些扩展名的文件,并将路径写入文件:

auto get_files(_In_ const std::wstring root, // root dir of search
        _In_ const std::set<std::string> &ext, // extensions to search for)
        _Out_ std::wofstream &ret /* file to write paths to */) -> int

    HANDLE find = INVALID_HANDLE_VALUE;

    // check root path
    
        LPCWSTR root_path = root.c_str();
        DWORD root_attrib = GetFileAttributesW(root_path);
        if(root_attrib == INVALID_FILE_ATTRIBUTES) return 1; // root doesn't exist
        if(!(root_attrib & FILE_ATTRIBUTE_DIRECTORY)) return 2; // root isn't a directory
    

    LPCWSTR dir;
    WIN32_FIND_DATAW fd;

    // dir concat
    
        std::wstring x = root.c_str();
        x.append(L"\\*");
        dir = x.c_str();
    


    find = FindFirstFileW(dir, &fd);

    do 
        if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) // current file is a dir
            get_files(dir, ext, ret);
        else 
            LPCWSTR current_ext = PathFindExtensionW(fd.cFileName);
            if(ext.find(current_ext) != ext.end()) 
                ret << fd.cFileName << '\n';
            
        
     while (FindNextFileW(find, &fd) != 0);

    FindClose(find);

    return 0;


我收到以下错误:

E0304 重载函数“std::set<_kty _pr _alloc>::find [with _Kty=std::string, _Pr=std::less, _Alloc=std::allocator]”的实例不匹配参数列表

还有这个。

C2664 'std::_Tree_const_iterator>> std::_Tree>::find(const std::basic_string,std::allocator> &) const': 无法将参数 1 从 'const wchar_t *' 转换为 'const std ::basic_string,std::allocator> &'

【问题讨论】:

第二个错误说明了一切:cannot convert argument 1 from 'const wchar_t *' to (the worked out version of) std::string. 还要注意dir 指向被销毁的std::wstring 的内容。如果这行得通,那只是偶然。 您无法将std::strings 与std::wstrings 进行比较。因此,要么将您的std::wstring 文件名转换为std::string,要么使用std::wstrings 的std::set。您的选择。除非您使用指向已删除 std::string 的指针来修复未定义的行为,否则请准备好处理随机、不可预测、神秘的错误。 【参考方案1】:

两个问题:

    std::set&lt;std::string&gt; &amp;extLPCWSTR current_ext 之间的类型冲突。您可以使用std::set&lt;std::wstring&gt; &amp;ext 来解决您的 E0304 错误。 正如@Botje 指出的,请注意std::wstring x 工作范围。您可以移除外部支架。

以下代码为我成功编译。请检查:

#include <shlwapi.h>
#include <set>
#include <fstream>

auto get_files(_In_ const std::wstring root, // root dir of search
    _In_ const std::set<std::wstring> &ext, // extensions to search for)
    _Out_ std::wofstream &ret /* file to write paths to */) -> int

    HANDLE find = INVALID_HANDLE_VALUE;

    // check root path
    
        LPCWSTR root_path = root.c_str();
        DWORD root_attrib = GetFileAttributesW(root_path);
        if (root_attrib == INVALID_FILE_ATTRIBUTES) return 1; // root doesn't exist
        if (!(root_attrib & FILE_ATTRIBUTE_DIRECTORY)) return 2; // root isn't a directory
    

    LPCWSTR dir;
    WIN32_FIND_DATAW fd;

    // dir concat
    std::wstring x = root.c_str();
    x.append(L"\\*");
    dir = x.c_str();

    find = FindFirstFileW(dir, &fd);

    do 
        if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) // current file is a dir
            get_files(dir, ext, ret);
        else 
            LPCWSTR current_ext = PathFindExtensionW(fd.cFileName);
            if (ext.find(current_ext) != ext.end()) 
                ret << fd.cFileName << '\n';
            
        
     while (FindNextFileW(find, &fd) != 0);

    FindClose(find);

    return 0;

至于第二个错误C2664我无法重现。确保向您发布重现这两个错误的确切代码。

【讨论】:

以上是关于C ++递归搜索具有某些扩展名的文件的主要内容,如果未能解决你的问题,请参考以下文章

linux 上查找包含特定文本的所有文件

如何递归地查找具有文本模式的文件,不包括某些目录和文件[重复]

如何递归遍历目录以删除具有某些扩展名的文件

在Windows中递归删除具有指定名称的文件夹的命令行工具?

复制具有特定父目录的所有文件,同时维护目录树

递归搜索根目录和子文件夹中的文件[重复]