【问题标题】:Compare relationship of two folder比较两个文件夹的关系
【发布时间】:2020-01-15 05:53:27
【问题描述】:

场景

PROCEDURE A 从网络服务收集文件,并将它们复制到根文件夹。有时文件会复制到根目录的子文件夹中,例如:

c:\root\file1
c:\root\file2
c:\root\filea
c:\root\<unique random name>\fileA

我怀疑(但我不确定)Web 服务在 linux 系统上运行并且文件名区分大小写。因此,文件被复制到 Windows 文件系统上,当发生大写/小写冲突时,文件被复制到子文件夹中。子文件夹具有唯一的随机生成的名称。

PROCEDURE B 扫描 和子文件夹中的文件以存档它们。正确归档的文件将被删除。 PROCEDURE APROCEDURE B 不会同时运行。

现在我的任务...我要删除根目录的空子文件夹。

第一个解决方案(最简单的)

当程序 B 结束时,我可以扫描根目录的空子文件夹,结束然后删除它们。嗯...

DWORD DeleteEmptySubFolder(LPCSTR szRootFolder)
{
    DWORD dwError = 0;

    CString sFolder(szRootFolder);
    sFolder += "*.*";

    CFileFind find_folder;
    BOOL bWorking = find_folder.FindFile(sFolder);
    while (bWorking)
    {
        bWorking = find_folder.FindNextFile();
        if(find_folder.IsDots())
            continue;

        if(find_folder.IsDirectory())
        {
            if(PathIsDirectoryEmpty(find_folder.GetFilePath()))
            if(!RemoveDirectory(find_folder.GetFilePath()))
                dwError = GetLastError();
        }
    }

    return dwError;
}

现在的问题是:我无法控制 PROCEDURE B,而且我不知道它何时结束。 PROCEDURE B可以在归档每个单独的文件后调用用户函数。

第二个解决方案(足够但不太有效)

我还是可以调用上面的函数

DWORD DeleteEmptySubFolder(LPCSTR szRootFolder)

确实效率不高,它会扫描每个归档文件的根目录下的所有子文件夹,但只会删除空的子文件夹。

第三种解决方案(应该可以)

当程序 B 调用用户函数时,我知道归档文件的根文件夹和完整路径。所以我可以检查文件的文件夹是否是根目录的子文件夹:

#define EQUAL_FOLDER        0
#define A_SUBFOLDER_OF_B    1
#define B_SUBFOLDER_OF_A    2
#define UNRELATED_FOLDER    3
int CompareFolderHiearachy(LPCSTR szFolderA, LPCSTR szFolderB)
{
    if(_stricmp(szFolderA, szFolderB))
    {
        // StrStrI - Windows function (from shlwapi.dll) which finds the first occurrence of a substring within a string (the comparison is not case-sensitive).
        if(StrStrI(szFolderA, szFolderB) == szFolderA)
            return A_SUBFOLDER_OF_B;
        else if(StrStrI(szFolderB, szFolderA) == szFolderB)
            return B_SUBFOLDER_OF_A;
        else
            return UNRELATED_FOLDER;
    }
    else
        return EQUAL_FOLDER;
}

也许这个解决方案在我的场景中可以正常工作,但它只能处理文件夹/文件名一致的情况。例如:

本地磁盘:

root: C:\folder\
filename: c:\folder\subfolder\fileA

映射磁盘:

root: Z:\folder\
filename: Z:\folder\subfolder\fileA

UNC:

root: \\SERVER\folder\
filename: \\SERVER\folder\subfolder\fileA

现在我的太笼统抽象问题,我可以在最坏的情况下检查两个文件夹的层次结构/关系吗?

\\server\folder1\folder2 (UNC)
z:\folder2 (network drive).

甚至最糟糕的......

\\MYPC\folder1\folder2
c:\folder2

也许我在问一个有点反常的问题……但这非常具有挑战性和吸引力,不是吗?

非常感谢。

【问题讨论】:

  • “解决”此问题的第一步是访问 stackoverflow.com 的help center,获取tour,并在此处发布您的第一个问题之前学习How to Ask 问题。通过这种方式,您将知道在 stackoverflow.com 上应该问什么样的问题才能获得有用的答案,而不是因为离题而被否决和关闭。
  • 这是不可能的(而且您还需要精简硬链接和重定向)。这感觉像是一个 XY 问题,即为什么你需要知道文件夹嵌套?
  • 不是一个完整的答案,但看看superuser.com/questions/135752/…
  • 我认为你的问题主要集中在第三个例子上。这一点我尝试用MD5来区分,因为文件夹没有MD5,所以我对比了文件夹的内容来判断网络共享文件夹是否和本地文件夹一样。但是我也发现了一个问题,就是如果我的PC上有两个相同的文件夹,文件夹的内容都是复制的,所以MD5是一样的,而且两个文件夹是共享的,那怎么区分是哪个文件夹呢?
  • @RichardCritten是的,我认为可能是一个 XY 问题,我正在尝试为一个过于抽象和过于笼统的问题找到一个超级解决方案。我将重新考虑整个问题,然后我将重新编辑问题。谢谢。

标签: c++ windows visual-studio mfc


【解决方案1】:

我改进了第三个解决方案;它可以解决几种情况,但不幸的是它不能处理所有可能的情况。

#define ERROR_OCCURED       -1
#define EQUAL_FOLDER        0
#define A_SUBFOLDER_OF_B    1
#define B_SUBFOLDER_OF_A    2
#define UNRELATED_FOLDER    3
int CompareFolderHiearachy(LPCSTR szFolderA, LPCSTR szFolderB)
{
    char pBuffer[32767];
    DWORD dwBufferLength = 32767;

    UNIVERSAL_NAME_INFO * unameinfo = reinterpret_cast< UNIVERSAL_NAME_INFO *>(pBuffer);

    DWORD dwRetVal = WNetGetUniversalName(szFolderA, UNIVERSAL_NAME_INFO_LEVEL, reinterpret_cast<LPVOID>(pBuffer), &dwBufferLength);
    if(dwRetVal != NO_ERROR && dwRetVal != ERROR_NOT_CONNECTED && dwRetVal != ERROR_BAD_DEVICE)
        return ERROR_OCCURED;

    CString sFolderA(unameinfo->lpUniversalName ? unameinfo->lpUniversalName : szFolderA);

    ZeroMemory(pBuffer, dwBufferLength);

    dwRetVal = WNetGetUniversalName(szFolderB, UNIVERSAL_NAME_INFO_LEVEL, reinterpret_cast<LPVOID>(pBuffer), &dwBufferLength);
    if(dwRetVal != NO_ERROR && dwRetVal != ERROR_NOT_CONNECTED && dwRetVal != ERROR_BAD_DEVICE)
        return ERROR_OCCURED;

    CString sFolderB(unameinfo->lpUniversalName ? unameinfo->lpUniversalName : szFolderB);

    if(_stricmp(sFolderA, sFolderB))
    {
        // StrStrI - Windows function (from shlwapi.dll) which finds the first occurrence of a substring within a string (the comparison is not case-sensitive).
        if(StrStrI(sFolderA, sFolderB) == static_cast<LPCSTR>(sFolderA))
            return A_SUBFOLDER_OF_B;
        else if(StrStrI(szFolderB, sFolderA) == static_cast<LPCSTR>(sFolderB))
            return B_SUBFOLDER_OF_A;
        else
            return UNRELATED_FOLDER;
    }
    else
        return EQUAL_FOLDER;
}

无法解决以下问题:

folder A: \\MY_PC\shared_folder\folderA
folder B: C:\shared_folder
(\\MY_PC\shared_folder and C:\shared_folder are the sane folder)

和:

folder A: \\SERVER\shared_folderA\shared_folderB
folder B: \\SERVER\shared_folderB

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 2012-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多