arcy
arcy

Reputation: 13153

determining symbolic links or junctions from Java on Windows

I thought I had read that if the absolute and canonical paths of a given file did not match, that that meant the file was a symbolic link.

I'm on Windows 10, and it has things it calls "Junctions"; the above test finds identical strings for those two items. I also have found no other way to distinguish these files, having tried the calls below:

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;

public class WindowsFilePlay2
{
  public static void main(String[] args)
  {
    WindowsFilePlay2 play2 = new WindowsFilePlay2();
    play2.go();
  }
  
  private void go()
  {
    File[] fileList = { new File("c:\\Users\\Ralph\\AppData\\Local\\")
                       ,new File("c:\\Users\\Ralph\\AppData\\")
                       ,new File("c:\\users\\ralph\\")
                      };
    try
    { 
      for (File file : fileList)
      {
        Path    filePath    = file.toPath();
        String  absolute    = file.getAbsolutePath();
        String  canonical   = file.getCanonicalPath();
        String  realPath    = filePath.toRealPath().toString();
        boolean answer      = Files.isSymbolicLink(filePath);
        boolean isFile      = file.isFile();
        boolean isAbsolute  = file.isAbsolute();
        boolean isDirectory = file.isDirectory();
        boolean isHidden    = file.isHidden();
        boolean isReadable  = Files.isReadable(filePath);
        
        BasicFileAttributes attributes = Files.readAttributes(filePath, BasicFileAttributes.class);
        boolean isLink      = attributes.isSymbolicLink();
        boolean isOther     = attributes.isOther();
        
        absolute = absolute.toLowerCase();
        canonical = canonical.toLowerCase();
        
        System.out.printf("filePath    %s%n"
                        + "absolute    %s%n"
                        + "canonical   %s%n"
                        + "realPath    %s%n"
                        + "answer      %b%n"
                        + "isFile      %b%n"
                        + "isAbsolute  %b%n"
                        + "isDirectory %b%n"
                        + "isHidden    %b%n"
                        + "isLink      %b%n"
                        + "isOther     %b%n"
                        + "isReadable  %b%n"
                        + "%n"
                        , filePath.toString(), absolute, canonical, realPath, answer, isFile, isAbsolute, isDirectory, isHidden, isLink, isOther, isReadable
                         );
      }
    }
    catch (IOException ioe)
    {
      ioe.printStackTrace();
    }
  }
}

The output from this:

filePath    c:\Users\Ralph\AppData\Local
absolute    c:\users\ralph\appdata\local
canonical   c:\users\ralph\appdata\local
realPath    C:\Users\ralph\AppData\Local
answer      false
isFile      false
isAbsolute  true
isDirectory true
isHidden    false
isLink      false
isOther     false
isReadable  true

filePath    c:\Users\Ralph\AppData
absolute    c:\users\ralph\appdata
canonical   c:\users\ralph\appdata
realPath    C:\Users\ralph\AppData
answer      false
isFile      false
isAbsolute  true
isDirectory true
isHidden    true
isLink      false
isOther     false
isReadable  true

filePath    c:\users\ralph
absolute    c:\users\ralph
canonical   c:\users\ralph
realPath    C:\Users\ralph
answer      false
isFile      false
isAbsolute  true
isDirectory true
isHidden    false
isLink      false
isOther     false
isReadable  true

But AppData and AppData\Local are not real files; they're junctions or links or whatever to other files. I don't know what they would be called in the Java API. My program wants to avoid them, since it is going through the actual directories on the disk and does not want to visit any directory subtrees twice. So how can I determine that I have one of these, whatever they're called?

Upvotes: 3

Views: 668

Answers (1)

arcy
arcy

Reputation: 13153

User error -- OP here, I was using the translation of the Junctions instead of the junctions themselves, e.g., c:\users\ralph\Application Data\ is what I should be testing -- that's the junction -- and it translates to c:\users\ralph\AppData\Roaming. But I was testing the latter, expecting to find some way of finding out it was a link or something, but it is not. When I test with the actual Windows Junction, the realPath value from the output above is different than the filePath value.

Thanks to those who responded.

Upvotes: 2

Related Questions