为什么 Windows 上的目录 Files.isHidden(Path) return false?

Why does Files.isHidden(Path) return false for directories on Windows?

来自 Files.isHidden(Path) 的文档(强调 我的):

Tells whether or not a file is considered hidden. The exact definition of hidden is platform or provider dependent. On UNIX for example a file is considered to be hidden if its name begins with a period character ('.'). On Windows a file is considered hidden if it isn't a directory and the DOS hidden attribute is set.

Depending on the implementation this method may require to access the file system to determine if the file is considered hidden.

由此我可以理解什么预期的行为是什么。但是,为什么 这是预期的行为?

我想知道的原因是 Files.isHiddenDosFileAttributes.isHidden 和 Windows' File Explorer 之间的行为差​​异.例如,我可以进入 File Explorer 并将一个目录设置为隐藏,它将不再显示(除非我将其配置为显示隐藏项目)。如果我测试所述目录是否被 Java 隐藏,那么 Files.isHidden returns falseDosFileAttributes.isHidden returns true。您可以使用以下代码对此进行测试:

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.DosFileAttributes;

public class Main {

  public static void main(String[] args) throws Exception {  
    final var directory = Path.of(args[0]).toAbsolutePath().normalize();
    final var store     = Files.getFileStore(directory);
    final var dosAttrs  = Files.readAttributes(directory, DosFileAttributes.class);

    System.out.println("Directory     : " + directory);
    System.out.println("FileStore     : " + store.name() + " [" + store.type() + "]");
    System.out.println("Hidden (Files): " + Files.isHidden(directory));
    System.out.println("Hidden (Dos)  : " + dosAttrs.isHidden());
  }

}

注意:我使用的是 Windows 10 和 OpenJDK 11.0.1。我的文件系统是 NTFS.


运行 这与:

java Main.java C:\path\to\hidden\directory

我得到:

Directory     : C:\path\to\hidden\directory
FileStore     : OS [NTFS]
Hidden (Files): false
Hidden (Dos)  : true

注意:此行为似乎是 WindowsFileSystemProvider 的一部分。方法 Files.isHidden(Path) 只是将调用转发给参数 FileSystem 的提供者。实现基本上是:

DosFileAttributes attrs = ...; // get attributes
return !attrs.isDirectory() && attrs.isHidden();

我发现这个 (non)-issue (JDK-8170334),其中一条评论说:

I don't think we have a bug here because the hidden attribute is meaningless on directories.

然而 File Explorer,它是 Windows 上的核心软件,其行为就像隐藏属性在目录上 而不是 没有意义.那么,为什么 Windows 上的 Java 实现会考虑 Path 是否指向目录?或者 Java 是否正确并且 文件资源管理器 正在做非标准的事情?

我倾向于认为 File Explorer 是正确的,因为 CMD(通过 dir)和 PowerShell(通过Get-ChildItem)也不会列出隐藏目录;除非指定了适当的选项。

我检查了 documentation Microsoft 为 Windows 平台提供的文件属性。它说如果设置属性 FILE_ATTRIBUTE_HIDDEN = 2 (0x2)

The file or directory is hidden. It is not included in an ordinary directory listing.

正如我在 class sun.nio.fs.WindowsConstants 中看到的那样,DosFileAttributes.isHidden() 方法使用了相同的值定义 - public static final int FILE_ATTRIBUTE_HIDDEN = 0x00000002; 根据我的理解应该映射与 Windows 可用的属性一对一,因此通常目录的 hidden 标志应该以与常规文件相同的方式工作。 关于操作 system/file 系统集成,此行为似乎是不正确的。