Win32 函数判断文件是否是目录的后代

发布于 2024-10-27 02:08:13 字数 257 浏览 8 评论 0原文

在 C++、Windows 中,我有 2 个文件路径:

  • Path1:目录
  • Path2:文件或目录

如何判断 Path2 是否是 Path1 的后代?有没有 Shell 函数可以实现这一点?我搜索了 Shell API,但没有找到。

注意:我不想自己比较字符串,除非有一种安全的方法可以使路径具有可比性(处理短名称、相关项等......)。

In C++, Windows, I have 2 file paths:

  • Path1: Directory
  • Path2: File or Directory

How can I tell if Path2 is a descendant of Path1? Is there a Shell function for that? I have searched the Shell API and could not find any.

Note: I don't want to compare the string myself, unless there is a safe way to make the path comparable (handle short names, relative items, etc...).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不顾 2024-11-03 02:08:13

我不认为 API 中有方便的函数可以为您解答这个问题。但我也不认为编写一个强大的函数来做到这一点并不太难。概要如下:

  1. 确保 Path1 和 Path2 是绝对路径。
  2. 检查 Path1 和 Path2 是否引用相同的文件系统对象(更多信息见下文)。
  3. 如果是这样,那么你的函数返回 true。
  4. 如果不从 Path2 中删除姓氏,即删除最后的路径分隔符(\ 或 /)及其后面的所有内容。
  5. 如果步骤 4 未能删除任何文本(例如,没有剩余路径分隔符),则您已到达根级别,并且您的函数返回 false。
  6. 转至 2。

现在,如何检查两个名称是否引用同一文件系统对象。最安全的方法是调用 GetFileInformationByHandle () 对于两个名称,并比较 dwVolumeSerialNumbernFileIndexLownFileIndexHigh。如果全部相等,则这两个名称引用同一个对象。

请注意,仅比较字符串是不够的,因为单个文件系统对象可以有许多不同的名称。例如硬链接、符号链接、连接、UNC 与映射驱动器号等。

I don't believe that there is a handy function in the API to answer this for you. But I also don't think it's too hard to write a robust function to do this. Here's the outline:

  1. Makes sure that Path1 and Path2 are absolute paths.
  2. Check if Path1 and Path2 refer to the same file system object (more on this below).
  3. If so then your function returns true.
  4. If not strip the last name off Path2, i.e. remove the final path separator (\ or /) and everything that follows it.
  5. If step 4 failed to remove any text (e.g. there are no path separators left) then you have reached the root level and your function returns false.
  6. Go to 2.

Now, how to check that two names refer to the same file system object. The safest way to do so is to call GetFileInformationByHandle() for both names, and compare dwVolumeSerialNumber, nFileIndexLow, nFileIndexHigh. If all are equal then the two names refer to the same object.

Note that it's not enough to compare strings because a single file system object can have many different names. For example hardlinks, symlinks, junctions, UNC vs mapped drive letters and so on.

情绪少女 2024-11-03 02:08:13

您可以使用 PathCommonPrefix 来比较获得公共前缀的两条路径。然后将公共前缀与 Path1(您的目录)进行比较。

如果两者相等,则 Path2 应该是后代。

或者,您也许可以在不使用 out 缓冲区的情况下逃脱,只需为第三个参数传递 NULL 并检查返回值(公共前缀字符的计数),等于 Path1 的长度。

PathCommonPrefix 的文档示例来看,PathCommonPrefix 看起来并没有在“common”前缀中包含尾随目录分隔符,因此您必须去掉尾随目录分隔符Path1 中的 sep 或相应地调整结果的比较,以防止缺少尾随 sep。

You could use PathCommonPrefix to compare the two paths to get a common prefix. Then compare the common prefix to Path1 (your directory).

If the two are equal then Path2 should be a descendant.

Or you maybe able to get away without using an out buffer and just pass NULL for the third parameter and check that the return value, which is the count of common prefix characters, is equal to Path1's length.

From the PathCommonPrefix's doc's example, it doesn't look like PathCommonPrefix includes trailing directory separators in the 'common' prefix, so you'll have to strip off the trailing sep in Path1 or adjust your comparison of the result accordingly for lack of trailing sep.

毁我热情 2024-11-03 02:08:13

这是我提出的一个解决方案,到目前为止似乎有效(在我有限的测试中)。它测试文件是否是直接后代,并获取相对路径。它基于 PathRelativePathTo

BOOL PathDirectRelativePathTo(LPWSTR pszPath, LPCWSTR pszFrom, DWORD dwAttrFrom, LPCWSTR pszTo, DWORD dwAttrTo)
{
    return PathRelativePathTo(pszPath, pszFrom, dwAttrFrom, pszTo, dwAttrTo) && pszPath[1] == L'\\';
}

前提是,当文件是直系后代时,PathRelativePathTo获取的相对路径以.\开头。当它不是直系后代时,相对路径以 .. 开头。所以这个函数测试相对路径的第二个字符是否是\。但同样,我只是想出了这个,所以也许那里潜伏着一些问题。

Here's a solution that I came up and that seems to work so far (in my limited testing). It tests whether the file is a direct descendant, and also obtains the relative path. It's based on PathRelativePathTo.

BOOL PathDirectRelativePathTo(LPWSTR pszPath, LPCWSTR pszFrom, DWORD dwAttrFrom, LPCWSTR pszTo, DWORD dwAttrTo)
{
    return PathRelativePathTo(pszPath, pszFrom, dwAttrFrom, pszTo, dwAttrTo) && pszPath[1] == L'\\';
}

The premise is that when a file is a direct descendant, the relative path obtained by PathRelativePathTo starts with .\. When it's not a direct descendant, the relative path starts with ... So this function tests whether the second character of the relative path is a \. But again, I just came up with this, so perhaps there are some problems lurking in there somewhere.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文