如何在不遵循符号链接的情况下确定文件的规范路径?

时间:2017-08-29 12:12:09

标签: java io filesystems nio symlink

假设我有以下java.io.File和相应的java.nio.file.Path个对象:

final String windir = "WINNT";
final String comspec = "cmd.exe";
final File absoluteFile = new File(format("C:\\./foo/../bar/../%s/./././././SYSTEM32/../system/../System32/%s", windir, comspec)).getAbsoluteFile();
final Path absolutePath = absoluteFile.toPath();

现在,我想确定规范路径,i。即删除所有...路径条目,以便生成的路径为C:\WINNT\System32\cmd.exe

java.io.File.getCanonicalPath()很好,除了它遵循 Unices 上的符号链接,我希望避免这种情况。

另一方面,

java.nio.file.Path.toRealPath(NOFOLLOW_LINKS)返回规范路径,不带符号链接,但它会抛出java.nio.file.NoSuchFileException

如何确定文件的规范路径

  • 以安全的方式(以便在文件不存在时不会抛出异常),
  • 以独立于平台的方式,
  • 没有遵循符号链接?

到目前为止,我找到的唯一解决方案是回归旧的java.io API:

@NonNull Path toCanonicalPath(final @NonNull Path path) throws IOException {
    try {
        /*
         * Fails for nonexistent files.
         */
        return path.toRealPath(NOFOLLOW_LINKS);
    } catch (final NoSuchFileException ignored) {
        /*
         * This one is fine except it always follows symbolic links on Unices.
         */
        return path.toFile().getCanonicalFile().toPath();
    } catch (final FileSystemException ignored) {
        /*
         * Thrown when there's a file/directory conflict, e. g.
         * for a non-existent file "foo/bar", "foo" already
         * exists and is a symlink, not a directory. In this
         * case, we can't use the File#getCanonicalFile() call.
         */
        return path.toAbsolutePath();
    }
}

有没有不那么丑陋的方法?

1 个答案:

答案 0 :(得分:0)

path.toAbsolutePath().normalize()实际上可以解决问题。

考虑一下,我们有一个指向/var/spool/mail的{​​{1}}符号链接:

/var/mail

在以上示例中,在两种情况下,规范路径均以未解析的符号链接打印:

final Path path = Paths.get("/var/./spool/../spool//mail/./");
System.out.println(path.toAbsolutePath().normalize());
System.out.println(path.toRealPath(NOFOLLOW_LINKS));