Java 1.6 – determinar enlaces simbólicos

En una clase DirectoryWalker, quiero saber si una instancia de File es realmente un enlace simbólico a un directorio (suponiendo que el walker camine en sistemas UNIX). Dado que ya sé que la instancia es un directorio, ¿sería la siguiente una condición confiable para determinar el enlace simbólico?

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

La técnica utilizada en Apache Commons utiliza la ruta canónica al directorio principal, no el archivo en sí. No creo que pueda garantizar que una discrepancia se deba a un enlace simbólico, pero es una buena indicación de que el archivo necesita un tratamiento especial.

Este es el código Apache (sujeto a su licencia ), modificado para compacidad.

 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 no proporciona dicho acceso de bajo nivel al sistema de archivos. Parece que NIO 2 , que debería incluirse en Java 1.7, tendrá soporte para enlaces simbólicos. Un borrador de la nueva API está disponible. Aquí se mencionan enlaces simbólicos, crearlos y seguirlos es posible. No estoy exactamente seguro de qué método debería usarse para averiguar si un archivo es un enlace simbólico. Hay una lista de correo para discutir sobre NIO 2: tal vez lo sepan.

Además, file.isFile() cuidado con file.isFile() y file.isDirectory() ambos devuelven resultados basados ​​en el archivo resuelto y, por lo tanto, ambos devuelven false cuando el file hace referencia a un enlace simbólico donde el destino no existe.

(Sé que esta no es una respuesta útil en sí misma, pero me hizo tropezar un par de veces, así que pensé que debería compartirla)

Parece que getCanonicalPath() puede hacer otras cosas que pueden hacer que sea diferente de la ruta absoluta.

Este método primero convierte este nombre de ruta a forma absoluta si es necesario, como si invoca el método getAbsolutePath () y luego lo mapea a su forma única de una manera dependiente del sistema. Esto generalmente implica eliminar nombres redundantes como “.” y “..” desde la ruta, resolviendo enlaces simbólicos (en plataformas UNIX) y convirtiendo letras de unidad en un caso estándar (en plataformas Microsoft Windows).

Pero podría funcionar para la gran mayoría de sus casos de uso; Su experiencia puede ser diferente.

Si ya está codificando algo específicamente para * nix, entonces podría hacer un comando de shell de Java como este:

 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"); 

Eso es muy específico para * nix, pero al menos funciona.

Perdón por responder a una publicación tan antigua, pero hace tiempo que estaba buscando una solución para sistemas Windows y algunas de las respuestas anteriores no me funcionaron. Si no está interesado en la compatibilidad multiplataforma y solo necesita una solución para Windows, la siguiente técnica funcionó bien para mis propósitos.

 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 } } 

Pensé que compartiría algo de buena suerte que tuve al tratar este tema. Estoy usando JDK 1.6.0_23 y no puedo beneficiarme de NIO2. Estoy comstackndo y ejecutando SOLAMENTE Windows 7 / x64, por lo que el kilometraje puede variar en otros entornos. Lamentablemente, otras soluciones aquí no me funcionaron para evitar las NullPointerExceptions causadas cuando intentaba atravesar un cruce (probablemente porque junction! = Symlink ….). Si bien no estoy limitado por la versión JDK, decidí seguir con el problema un poco más.

Tenía este código que causaría una NullPointerException si se usa en un enlace simbólico o cuando se encuentra con el directorio ‘System Volume Information’. (Tenga en cuenta que traverseItem.f () devuelve un objeto de tipo java.io.File)

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

Entonces, supuestamente es un directorio, pero al llamar a listFiles () en él se genera un NPE. ¿Qué hacer? Espié el método list () y me pregunté si mostraría el mismo comportamiento. Lo que descubrí fue lo siguiente:

La lista de llamadas () en un archivo que describe una carpeta vacía devuelve una matriz String [] de longitud cero. Sin embargo, la lista de llamadas () en un archivo que describe una unión que de otra manera se bloquearía de listFiles () devuelve null

Pude evitar NullPointerExceptions agregando la siguiente prueba antes de llamar a listFiles ()

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

Queda por probar exhaustivamente todos los casos de unión, enlace simbólico, enlace rígido, y me atrevo a mencionarlo, atajo, pero esto puede ayudar a algunos.