程式扎記: [ Java 常見問題 ] Detecting a symlink in Java

標籤

2015年6月3日 星期三

[ Java 常見問題 ] Detecting a symlink in Java

Source From Here 
Question 
Given a Java 'File' object, how can I detect whether or not it refers to a symlink? Then resolve its real absolute path. 

How-To 
File.getCanonicalPath() resolves symlinks: 
A canonical pathname is both absolute and unique. The precise definition of canonical form is system-dependent. 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. 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).

From JDK8+, you can leverage Files.isSymbolicLink(Path path) to check the give path is symbolic or not. 

The technique used in Apache Commons uses the canonical path to the parent directory, not the file itself. 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: 
  1. public static boolean isSymlink(File file) throws IOException {  
  2.   if (file == null)  
  3.     throw new NullPointerException("File must not be null");  
  4.   File canon;  
  5.   if (file.getParent() == null) {  
  6.     canon = file;  
  7.   } else {  
  8.     File canonDir = file.getParentFile().getCanonicalFile();  
  9.     canon = new File(canonDir, file.getName());  
  10.   }  
  11.   return !canon.getCanonicalFile().equals(canon.getAbsoluteFile());  
  12. }  
For example, we first create a soft link and have a real file myfile.txt under the current path: 
$ ln -s /var/cache/ cache
$ ls -l ./cache
lrwxrwxrwx. 1 root root 11 Jan 8 00:30 ./cache -> /var/cache/

Then below is the testing groovy code: 
- test.groovy 
  1. #!/usr/bin/env groovy  
  2. import java.nio.file.attribute.BasicFileAttributes  
  3. import java.nio.file.attribute.PosixFileAttributes;  
  4. import java.nio.file.Files  
  5. import java.nio.file.Path;  
  6. import java.nio.file.Paths;  
  7.   
  8. public static boolean IsSymlink(File file) throws IOException {  
  9.   if (file == null)  
  10.     throw new NullPointerException("File must not be null");  
  11.   File canon;  
  12.   if (file.getParent() == null) {  
  13.     canon = file;  
  14.   } else {  
  15.     File canonDir = file.getParentFile().getCanonicalFile();  
  16.     canon = new File(canonDir, file.getName());  
  17.   }  
  18.   return !canon.getCanonicalFile().equals(canon.getAbsoluteFile());  
  19. }  
  20.   
  21. files = ["cache""myfile.txt"]  
  22.   
  23. for(fileName in files)  
  24. {  
  25.     File file = new File(fileName)  
  26.     printf("AbsolutePath: %s\n", file.getAbsolutePath())  
  27.     printf("CanonicalPath: %s\n", file.getCanonicalPath())  
  28.     //printf("Path: %s\n", cache.toPath())  
  29.     //PosixFileAttributes attrs = Files.readAttributes(file.toPath(), PosixFileAttributes.class);  
  30.     printf("Is Symbpolic? %s\n", IsSymlink(file))  
  31.     printf("==========================================\n")  
  32. }  
Execution Result: 
$ ./test.groovy
AbsolutePath: /root/cache
CanonicalPath: /var/cache
Is Symbpolic? true
==========================================
AbsolutePath: /root/myfile.txt
CanonicalPath: /root/myfile.txt
Is Symbpolic? false
==========================================

Supplement 
Using PosixFileAttributes : File Attribute

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!