简体   繁体   English

Java 1.6 - 确定符号链接

[英]Java 1.6 - determine symbolic links

In a DirectoryWalker class I want to find out if a File instance is actually a symbolic link to a directory (assuming, the walker walks on UNIX systems).在 DirectoryWalker 类中,我想确定 File 实例是否实际上是指向目录的符号链接(假设 walker 在 UNIX 系统上运行)。 Given, I already know the instance is a directory, would the following be a reliable condition to determine the symbolic link?鉴于,我已经知道该实例是一个目录,以下是否是确定符号链接的可靠条件?

File file;
// ...      
if (file.getAbsolutePath().equals(file.getCanonicalPath())) {
    // real directory ---> do normal stuff      
}
else {
    // possible symbolic link ---> do link stuff
}

The technique used in Apache Commons uses the canonical path to the parent directory, not the file itself. Apache Commons 中使用的技术使用父目录的规范路径,而不是文件本身。 I don't think that you can guarantee that a mismatch is due to a symbolic link, but it's a good indication that the file needs special treatment.我认为您不能保证不匹配是由符号链接引起的,但这很好地表明文件需要特殊处理。

This is Apache code (subject to their license ), modified for compactness.这是Apache 代码(受他们的许可),为了紧凑而修改。

public static boolean isSymlink(File file) throws IOException {
  if (file == null)
    throw new NullPointerException("File must not be null");
  File canon;
  if (file.getParent() == null) {
    canon = file;
  } else {
    File canonDir = file.getParentFile().getCanonicalFile();
    canon = new File(canonDir, file.getName());
  }
  return !canon.getCanonicalFile().equals(canon.getAbsoluteFile());
}

Java 1.6 does not provide such low level access to the file system. Java 1.6 不提供对文件系统的这种低级别访问。 Looks like NIO 2 , which should be included in Java 1.7, will have support for symbolic links.看起来应该包含在 Java 1.7 中的NIO 2将支持符号链接。 A draft of the new API is available.新 API 的草稿已发布。 Symbolic links are mentioned there , creating and following them is possible. 那里提到了符号链接,可以创建跟踪它们。 I'm not exactly sure that which method should be used to find out whether a file is a symbolic link.我不确定应该使用哪种方法来确定文件是否是符号链接。 There's a mailing list for discussing NIO 2 - maybe they will know.一个讨论 NIO 2的邮件列表- 也许他们会知道。

Also, watch out for file.isFile() and file.isDirectory() both returning results based on the resolved file and therefore both returning false when file refers to a symlink where the target doesn't exist.另外,注意file.isFile()file.isDirectory()都返回基于解析文件的结果,因此当file引用目标不存在的符号链接时,它们都返回false

(I know this isn't a useful answer in itself but it tripped me up a couple of times so thought I should share) (我知道这本身不是一个有用的答案,但它让我绊倒了几次,所以我认为我应该分享)

It looks like getCanonicalPath() can do other things that might make it different from the absolute path.看起来getCanonicalPath()可以做其他可能使其与绝对路径不同的事情。

This method first converts this pathname to absolute form if necessary, as if by invoking the getAbsolutePath() method, and then maps it to its unique form in a system-dependent way.如有必要,此方法首先将此路径名转换为绝对形式,就像调用 getAbsolutePath() 方法一样,然后以依赖于系统的方式将其映射到其唯一形式。 This typically involves removing redundant names such as "."这通常涉及删除冗余名称,例如“。” and ".." from the pathname, resolving symbolic links (on UNIX platforms), and converting drive letters to a standard case (on Microsoft Windows platforms).和路径名中的“..”,解析符号链接(在 UNIX 平台上),并将驱动器号转换为标准大小写(在 Microsoft Windows 平台上)。

But it might work for the vast majority of your use cases;但它可能适用于您的绝大多数用例; your mileage may vary.你的旅费可能会改变。

If you are already coding something specifically for *nix, then you could do a shell command from Java like this:如果您已经在专门为 *nix 编写代码,那么您可以从 Java 执行如下的 shell 命令:

Process p = Runtime.getRuntime().exec(new String[]{"test", "-h", yourFileName});
p.waitFor();
if (p.exitValue() == 0) 
   System.out.println("This file is a symbolic link");
else
   System.out.println("This file is not a symbolic link");

That's very specific to *nix, but it does at least work.这对 *nix 来说非常具体,但它至少可以工作。

Sorry to reply to such an old post, but I was looking for a solution for Windows systems some time back, and some of the previous answers didn't work out for me.很抱歉回复这么旧的帖子,但我前段时间一直在寻找适用于 Windows 系统的解决方案,而之前的一些答案对我来说并不奏效。 If you're not concerned with cross platform compatibility and only need a solution for Windows, the following technique worked well for my purposes.如果您不关心跨平台兼容性并且只需要一个适用于 Windows 的解决方案,那么以下技术对我的目的很有效。

File f = new File("whatever file or folder");
if (f instanceof ShellFolder) {
  ShellFolder sf = (ShellFolder)f;
  if (sf.isLink()) {
    // Your code when it's a link
  }
}

I thought I would share some good fortune I had in dealing with this issue.我想我会分享我在处理这个问题时的一些幸运。 I am using JDK 1.6.0_23 and so I cannot benefit from NIO2.我使用的是 JDK 1.6.0_23,所以我无法从 NIO2 中受益。 I am building and running on Windows 7 /x64 ONLY so mileage may vary in other environments.我仅在 Windows 7 /x64 上构建和运行,因此在其他环境中里程可能会有所不同。 Unfortunately, other solutions here did not work for me in avoiding NullPointerExceptions caused when attempting to traverse a junction (probably because junction != symlink....).不幸的是,这里的其他解决方案在避免尝试遍历连接时引起的 NullPointerExceptions 对我不起作用(可能是因为连接!= 符号链接....)。 While I am not constrained by JDK version, I decided to keep at the problem for a bit longer.虽然我不受 JDK 版本的限制,但我决定再解决这个问题一段时间。

I had this code which would cause a NullPointerException if used on a symbolic link or when encountering the 'System Volume Information' directory.我有这段代码,如果在符号链接上使用或遇到“系统卷信息”目录时会导致 NullPointerException。 (Note, traverseItem.f() returns an object of type java.io.File) (注意,traverseItem.f() 返回一个 java.io.File 类型的对象)

if (traverseItem.f().isDirectory) {
    for (File item : traverseItem.f().listFiles()) {

So, it is supposedly a directory but calling listFiles() on it causes an NPE.因此,它应该是一个目录,但在其上调用 listFiles() 会导致 NPE。 What to do?该怎么办? I spied the list() method and wondered if it would exhibit the same behavior.我监视了 list() 方法并想知道它是否会表现出相同的行为。 What I discovered was the following:我发现的是以下内容:

Calling list() on a File describing an empty folder returns a String[] array of length zero.在描述空文件夹的文件上调用 list() 返回长度为零的 String[] 数组。 However, calling list() on a File describing a junction which would otherwise crash from listFiles() returns null但是,在描述联结的文件上调用 list() 否则会从 listFiles() 崩溃返回 null

I was able to avoid the NullPointerExceptions by adding the following test before calling listFiles()通过在调用 listFiles() 之前添加以下测试,我能够避免 NullPointerExceptions

    String[] contents = traverseItem.f().list();
    if (contents != null) {  //Non-traversible if null, possibly junction or ???

It remains to exhaustively test all cases of junction, symbolic link, hard link, and dare I mention it, shortcut, but this may help some.仍然需要详尽地测试所有连接、符号链接、硬链接的情况,我敢提它,捷径,但这可能会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM