【问题标题】:Copy all files .doc or .docx in folder and subfolder into another folder将文件夹和子文件夹中的所有文件 .doc 或 .docx 复制到另一个文件夹中
【发布时间】:2022-01-13 01:47:20
【问题描述】:

我是 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:");

【问题讨论】:

  • 呃...find ... -exec 怎么了?
  • 这没什么问题,但这是一项要求我编写具有上述功能的 winapi 应用程序的任务,目前我一直在弄清楚为什么它不能正常工作:(跨度>
  • 如果可以使用 C++17,这种事情现在实际上更容易使用 std::filesystem 完成

标签: c++ winapi


【解决方案1】:
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 需要额外的头文件和库。如果由于某种原因它不可用,并且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';
    }
}

【讨论】:

  • 与其手动搜索扩展,不如考虑使用PathFindExtension()
  • @RemyLebeau 我忘了。已更新。
猜你喜欢
  • 2019-02-15
  • 2011-07-19
  • 1970-01-01
  • 2016-10-25
  • 2015-03-17
  • 1970-01-01
  • 2015-01-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多