Reputation: 29240
In java, a symbolic link in a Unix environment can be detected by comparing the file's canonical and absolute path. However, this trick does not work on windows. If I execute
mkdir c:\foo
mklink /j c:\bar
from the command line and then execute the following lines in java
File f = new File("C:/bar");
System.out.println(f.getAbsolutePath());
System.out.println(f.getCanonicalPath());
the output is
C:\bar
C:\bar
Is there any pre-Java 7 way of detecting a junction in windows?
Upvotes: 9
Views: 3583
Reputation: 6335
With nio it is possible to detect a junction/reparse point or symlink even without reflection or use of JNA:
public void isReparsePointOrSymlink(Path path) {
final var attribute = Files.getAttribute(path, "dos:attributes", LinkOption.NOFOLLOW_LINKS);
if (attribute instanceof Integer value) {
final boolean isJunctionOrSymlink = (value & 0x400) != 0;
return isJunctionOrSymlink;
}
return Files.isSymbolicLink(path);
}
Note, that Files.isSymbolicLink(path)
only returns true
for the symbolic link, not for the reparse point. If you need to distinguish between both and isReparsePointOrSymlink
returns true
, check also Files.isSymbolicLink
.
Upvotes: 0
Reputation: 29240
There doesn't appear to be any cross platform mechanism for this in Java 6 or earlier, though its a fairly simple task using JNA
interface Kernel32 extends Library {
public int GetFileAttributesW(WString fileName);
}
static Kernel32 lib = null;
public static int getWin32FileAttributes(File f) throws IOException {
if (lib == null) {
synchronized (Kernel32.class) {
lib = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
}
}
return lib.GetFileAttributesW(new WString(f.getCanonicalPath()));
}
public static boolean isJunctionOrSymlink(File f) throws IOException {
if (!f.exists()) { return false; }
int attributes = getWin32FileAttributes(f);
if (-1 == attributes) { return false; }
return ((0x400 & attributes) != 0);
}
EDIT: updated per comment about possible error return by getWin32FileAttributes()
Upvotes: 8
Reputation: 3499
You can try this dirty hack for windows
if (f.isDirectory() || f.isFile()) {
System.out.println("File or Directory");
} else {
System.out.println("Link");
}
Upvotes: -1
Reputation: 100013
The answer is 'no'. Junction points and symbolic links are not the same sort of thing. The JRE doesn't check for them, and so the functions you cite don't differentiate them.
Having said this, you might accomplish something with the following:
If the junctioned directory has contents, then the result of getting the canonical pathname of something down below it might be 'surprising' and reveal the situation, since it is likely to be a pathname under the target of the junction. This only works if the directory pointed to by the junction is, of course, non-empty.
Upvotes: 1