0

我想删除所有以子字符串开头的文件。

  CString Formatter = _T("C:\\logs\\test\\test_12-12-2018_1*.*");     
  DeleteFile(Formatter);

我打算用上面的代码删除以下文件

    C:\logs\test\test_12-12-2018_1_G1.txt
    C:\logs\test\test_12-12-2018_1_G2.txt
    C:\logs\test\test_12-12-2018_1_G3.txt
    C:\logs\test\test_12-12-2018_1_G4.txt

当我从 GetLastError 检查错误时,我得到 ERROR_INVALID_NAME。

知道如何解决这个问题吗?

4

2 回答 2

2

尽管您可以搜索文件名,然后分别调用DeleteFile每个文件名,但我的建议是使用 Windows shell 函数之一来代替。

例如,您可以使用如下代码:

#define _WIN32_IE 0x500

#include <windows.h>
#include <shellapi.h>
#include <shlobj.h>
#include <iostream>
#include <string>

static char const *full_path(std::string const &p) {
    static char path[MAX_PATH+2] = {0};
    char *ignore;
    GetFullPathName(p.c_str(), sizeof(path), path, &ignore);
    return path;
}

static int shell_delete(std::string const &name) {
    SHFILEOPSTRUCT op = { 0 };

    op.wFunc = FO_DELETE;
    op.pFrom = full_path(name);
    op.fFlags = FOF_ALLOWUNDO | FOF_SILENT | FOF_WANTNUKEWARNING | FOF_NOCONFIRMATION;
    return !SHFileOperation(&op);
}

int main(int argc, char **argv) {

    if ( argc < 2) {
        fprintf(stderr, "Usage: delete <filename> [filename ...]");
        return 1;
    }

    for (int i=1; i<argc; i++)
        shell_delete(argv[i]);    
}

这样做的一个明显优势是您可以传递FOF_ALLOWUNDO标志(正如我在上面的代码中所做的那样),它将文件移动到回收站而不是永久删除它。当然,如果你想对文件进行 nuked,你可以省略该标志。

根据您正在做的事情,还有一些其他标志可能会很方便,例如FOF_FILESONLY,仅删除文件,而不是可能与您指定的通配符匹配的目录,并且FOF_NORECURSION根本不会递归到子目录中。

Microsoft 认为SHFileOperation已过时,并已(在 Windows Vista 中,如果没记错的话)将其“替换”为IFileOperation. IFileOperation虽然它是一个 COM 接口,所以除非您在代码的其他地方使用 COM,否则很有可能使用它会增加相当多的额外工作(至少在这种情况下)很少或没有真正的优势。尤其是您已经在使用 COM,但是,这可能值得考虑。

于 2019-02-11T17:34:27.797 回答
2

DeleteFile不带通配符。看起来您需要一个FindFirstFile//循环将通配符转换为完整文件名列表FindNextFileFindClose

#include <windows.h>
#include <pathcch.h>
#pragma comment(lib, "pathcch.lib")

// (In a function now)
WIN32_FIND_DATAW wfd;
WCHAR wszPattern[MAX_PATH];
HANDLE hFind;
INT nDeleted = 0;
PathCchCombine(wszPattern, MAX_PATH, L"C:\\Logs\\Test", L"test_12-12-2018_1*.*");
SetCurrentDirectoryW(L"C:\\Logs\\Test");

hFind = FindFirstFileW(wszPattern, &wfd);
if(hFind == INVALID_HANDLE_VALUE)
{
    // Handle error & exit
}
do
{
    DeleteFileW(wfd.cFileName);
    nDeleted++;
} 
while (FindNextFileW(hFind, &wfd));
FindClose(hFind);

wprintf(L"Deleted %d files.\n", nDeleted);

请注意PathCchCombineFindFirstFileW、 和DeleteFileW都可能失败,并且健壮的代码会检查它们的返回值并适当地处理失败。此外,如果FindNextFileW返回 0 并且最后一个错误代码不是ERROR_NO_MORE_FILES,那么它由于实际错误而失败(不是因为没有任何东西可以找到),这也需要处理。

此外,如果您关心速度(您在帖子中关于删除同一目录中的四个文件的示例似乎不需要它),请将该行替换为hFind = FindFirstFileW(...)

hFind = FindFirstFileExW(wszPattern, FindExInfoBasic, (LPVOID)&wfd, FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH);
于 2019-02-11T16:00:38.893 回答