std::filesystem "root_name" 定义在 windows 上被破坏

std::filesystem "root_name" definition broken on windows

我感觉 C++ 文件系统标准在 windows 上被破坏了。它在很大程度上基于 Boost.filesystem,我刚刚在那里发现了一个严重的问题,它(可能)也存在于 std::filesystem 中:https://github.com/boostorg/filesystem/issues/99

本质就是"root_name"和"root_directory"的定义:

root-name(optional): identifies the root on a filesystem with multiple roots (such as "C:" or "//myserver"). In case of ambiguity, the longest sequence of characters that forms a valid root-name is treated as the root-name. The standard library may define additional root-names besides the ones understood by the OS API.

root-directory(optional): a directory separator that, if present, marks this path as absolute. If it is missing (and the first element other than the root name is a file name), then the path is relative and requires another path as the starting location to resolve to a file name.

这需要例如"C:\foo\bar.txt" 分解为:

现在的问题:这条路径的第一部分不是路径,至少不是原来的路径。这来自对windows的解释:

次要:“\foo\bar.txt”在windows上应该怎么解释?你有一个 "root_directory"(奇怪的是它不是一个目录而是一个目录 分隔符 )但是没有 "root_name" 因此路径不能是绝对的所以你没有"root_directory" 要么。叹息

所以由此我觉得"root_name"和"root_directory"不能分解(在windows上)。在 "C:\foo" 中,您将拥有 "C:\",在 "C:foo" 中,您将拥有 "C:"。或者要保留(奇怪定义的)"root_directory",您需要将 decompose "C:\foo" 设置为 "C:\"、"\" 和 "foo" 并与后者作斗争:Is that an绝对路径?其实是:"The folder 'foo' in the current working directory on drive C",很绝对吧?

但是你可以说 "absolute==independent of current working dir" 那么 "root_directory" 就有意义了:对于 "C:\foo" 它将是“\”,对于 "C:foo".[=15= 则为空]

所以问题:在像 "C:\foo" 这样的路径中将 "C:" 定义为 "root_name" 而不是 "C:\" 的标准是错误的,还是它只是无效的迭代用法期望前缀和为 "valid"?

的路径组件

您对 Windows 文件系统的解释不正确。目录 C:\ 是 "C" 驱动器的根目录,而不是 "the drive 'C'"。这与 C: 不同,后者是 "C" 驱动器的当前目录。只需尝试使用 Windows shell 并查看 C:<stuff> 相对于 C:\<stuff> 的表现如何。两者都将访问该驱动器上的内容,但两者都是从不同的目录开始的。

在 Windows 上用这些术语来思考它:

  • C: 表示 "Go to the current directory of the C drive".
  • \ 在路径的开头(在任何根名称之后)表示 "Go to the root directory of the current drive".
  • foo\ 表示 "Go into the directory called 'foo' within whatever directory we are currently in".
  • bar.txt 表示 "The file named 'bar.txt' in whatever directory we are currently in."

因此,C:\foo\bar.txt"的意思是:进入C盘当前目录,然后进入C盘根目录,再进入C盘根目录'foo'目录,然后访问C.

根目录'foo'目录下的文件'bar.txt'

同理,C:foo\bar.txt表示:进入C盘当前目录,然后进入C盘当前目录'foo'目录,然后访问文件'bar.txt'在C.

当前目录的'foo'目录下

这就是 Windows 路径的工作方式。这就是在 Windows shell 中键入这些内容的意思。因此,这就是 Boost/std 文件系统路径的设计方式。

But well you could say "absolute==independent of current working dir"

但这不是 std 文件系统定义的方式 the concept of "absolute path":

Absolute Path A path that unambiguously identifies the location of a file without reference to an additional starting location. The elements of a path that determine if it is absolute are operating system dependent.

所以 "relative" 和 "absolute" 是依赖于实现的。在 Windows 中,路径不是绝对路径,除非它同时包含 根名称和根目录。在 Windows 文件系统实现中,path("\foo\bar.txt").is_absolute() 将为假。

你要找的是root_path,见Filesystem TS § 8.4.9,路径分解:

path root_path() const;

Returns: root_name() / root_directory()

Microsoft defines it 的做法如下:

Common to both systems is the structure imposed on a pathname once you get past the root name. For the pathname c:/abc/xyz/def.ext:

  • The root name is c:.
  • The root directory is /.
  • The root path is c:/.
  • The relative path is abc/xyz/def.ext.
  • The parent path is c:/abc/xyz.
  • The filename is def.ext.
  • The stem is def.
  • The extension is .ext.

因此,真正的绝对路径应以 root_name + root_directoryroot_path.

开头

另请参阅 system_complete(p) 以解析其他驱动器上的当前目录:

Effects: Composes an absolute path from p, using the same rules used by the operating system to resolve a path passed as the filename argument to standard library open functions.

[Example: For POSIX based operating systems, system_complete(p) has the same semantics as absolute(p, current_path()).

For Windows based operating systems, system_complete(p) has the same semantics as absolute(p, current_path()) if p.is_absolute() || !p.has_root_name() or p and base have the same root_name(). Otherwise it acts like absolute(p, cwd) is the current directory for the p.root_name() drive. This will be the current directory for that drive the last time it was set, and thus may be residue left over from a prior program run by the command processor. Although these semantics are useful, they may be surprising. —end example]