将文件夹和子文件夹中的所有文件 .doc 或 .docx 复制到另一个文件夹中

Copy all files .doc or .docx in folder and subfolder into another folder

我是 C++ 和 winapi 的新手,目前正在开发一个项目来创建一个 winapi 应用程序,该应用程序具有将一个驱动器中的所有文件 .doc 和 .docx 复制到另一个文件夹的功能。 以下是我所做的,但似乎没有用:

谁能告诉我如何正确执行此操作?

void  cc(wstring inputstr) {
    TCHAR sizeDir[MAX_PATH];
    wstring search = inputstr + TEXT("\*");
    wcscpy_s(sizeDir, MAX_PATH, search.c_str());

WIN32_FIND_DATA findfiledata;
HANDLE Find = FindFirstFile(sizeDir, &findfiledata);

do {

    if (findfiledata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
        if (!wcscmp(findfiledata.cFileName, TEXT(".")) || !wcscmp(findfiledata.cFileName, TEXT(".."))) continue;
        //checking folder or file
        wstring dirfolder = inputstr + TEXT("\") + findfiledata.cFileName;
        cc(dirfolder);
    }
    else {
        wstring FileSearch = findfiledata.cFileName;
        //.doc or docx
        if (!wcscmp(FileSearch.c_str(), L".doc") || !wcscmp(FileSearch.c_str(), L".docx")) {
            TCHAR src[256] = L"D:\test\";
            wstring dirsrc = inputstr + TEXT("\") + findfiledata.cFileName;
            _tprintf(TEXT("  %s  \n"), dirsrc.c_str());
            wcscat_s(src, findfiledata.cFileName);
            CopyFile(dirsrc.c_str(), src, TRUE);
        }
    }

} while (FindNextFile(Find, &findfiledata) != 0); 
FindClose(Find);
}

调用函数时这里的inputstr就是我要搜索的驱动器,如cc(L"D:");

if (!wcscmp(FileSearch.c_str(), L".doc") || !wcscmp(FileSearch.c_str(), L".docx"))

这是比较整个文件名。我们只需要比较文件扩展名。 PathFindExtension 可用于查找文件扩展名:

const wchar_t* ext = PathFindExtension(findfiledata.cFileName);
if (_wcsicmp(ext, L".doc") == 0 || _wcsicmp(ext, L".docx") == 0)
{
    const std::wstring path = inputstr + L"\" + findfiledata.cFileName;
    std::wcout << path << '\n';
}

findfiledata 应为零初始化。

在该递归函数中添加 CopyFile 可能会导致问题。因为 FindNextFile 可以看到新复制的文件,并且该函数尝试再次复制它。

您可以将结果保存在字符串向量中,然后在 cc 完成后复制文件。

void cc(const std::wstring &inputstr, std::vector<std::wstring> &vec)
{
    std::wstring wildcard{ inputstr + L"\*" };
    WIN32_FIND_DATA find = { 0 };
    HANDLE handle = FindFirstFile(wildcard.c_str(), &find);
    if (handle == INVALID_HANDLE_VALUE)
        return;
    do
    {
        if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
            if (!wcscmp(find.cFileName, L".") || !wcscmp(find.cFileName, L".."))
                continue;
            const std::wstring dir = inputstr + L"\" + find.cFileName;
            cc(dir, vec);
        }
        else 
        {
            const wchar_t* ext = PathFindExtension(find.cFileName);
            if (_wcsicmp(ext, L".doc") == 0 || _wcsicmp(ext, L".docx") == 0)
            {
                const std::wstring path = inputstr + L"\" + find.cFileName;
                vec.push_back(path);
            }
        }
    } while (FindNextFile(handle, &find) != 0);
    FindClose(handle);
}

用作

std::vector<std::wstring> result;
cc(L"D:\test", result);
for (const auto& e : result)
    std::wcout << e << '\n';

注意,PathFindExtension requires additional headers and libraries. If it's not available for some reason, and std::filesystem不可用,这里有一个自己动手的方法:

std::wstring test = findfiledata.cFileName;
auto dot = test.find_last_of(L'.');
if (dot != std::wstring::npos)
{
    auto ext = test.substr(dot);
    for (auto& e : ext) e = towlower(e);
    if (ext == L".doc" || ext == L".docx")
    {
        std::wstring path = inputstr + L"\" + findfiledata.cFileName;
        std::wcout << path << '\n';
    }
}