Java, enumera solo los subdirectorios de un directorio, no los archivos

100

En Java, ¿cómo puedo enumerar solo los subdirectorios de un directorio?

Me gustaría usar la funcionalidad java.io.File, ¿cuál es el mejor método en Java para hacer esto?

Lokesh Paunikar
fuente

Respuestas:

141

Puede utilizar la clase File para enumerar los directorios.

File file = new File("/path/to/directory");
String[] directories = file.list(new FilenameFilter() {
  @Override
  public boolean accept(File current, String name) {
    return new File(current, name).isDirectory();
  }
});
System.out.println(Arrays.toString(directories));

Actualizar

El comentario del autor en esta publicación quería una manera más rápida, gran discusión aquí: ¿Cómo recuperar una lista de directorios RÁPIDAMENTE en Java?

Básicamente:

  1. Si controla la estructura del archivo, trataría de evitar entrar en esa situación.
  2. En Java NIO.2, puede utilizar la función de directorios para devolver un iterador para permitir una mayor escala. La clase de flujo de directorio es un objeto que puede utilizar para iterar sobre las entradas de un directorio.
Mohamed Mansour
fuente
hola, gracias por la respuesta. Pero no tengo que iterar sobre todos los elementos de un directorio. Tengo que enumerar directamente el subdirectorio del directorio. Porque tengo muchos archivos y solo unos pocos subdirectorios en un directorio, por lo que verificar isDirectory () lleva mucho tiempo. por favor respóndeme de otra manera.
Lokesh Paunikar
Actualicé mi publicación, en particular, eche un vistazo al comentario de Jon Skeet sobre la pregunta. Y la respuesta de NIO ya que Java NIO 2 tiene un iterador para la función de directorios que devuelve un flujo de directorios.
Mohamed Mansour
¿A qué comentario de Skeet te refieres? ¿Cuál es la respuesta de mejor rendimiento aquí?
Stealth Rabbi
107

Una solución Java 8 muy simple:

File[] directories = new File("/your/path/").listFiles(File::isDirectory);

Es equivalente a usar un FileFilter (también funciona con Java antiguo):

File[] directories = new File("/your/path/").listFiles(new FileFilter() {
    @Override
    public boolean accept(File file) {
        return file.isDirectory();
    }
});
headsvk
fuente
4
¿Cómo funciona el doble colon ::en este caso?
snickers10m
Noté que ninguna otra respuesta usa FileFilter, así que agregué la versión equivalente sin usar referencias de método. Para obtener más información sobre las referencias de métodos, consulte esta pregunta SO o este artículo .
headsvk
¿Esto obtiene subdirectorios o solo los directorios directamente debajo de / your / path /?
amadain
@amadain sin recursividad como se esperaba docs.oracle.com/javase/7/docs/api/java/io/File.html#listFiles ()
headsvk
14

@Mohamed Mansour casi estabas allí ... el argumento "dir" que estabas usando es en realidad la ruta actual, por lo que siempre volverá verdadero. Para ver si el niño es un subdirectorio o no, necesita probar ese niño.

File file = new File("/path/to/directory");
String[] directories = file.list(new FilenameFilter() {
  @Override
  public boolean accept(File current, String name) {
    return new File(current, name).isDirectory();
  }
});
System.out.println(Arrays.toString(directories));
Javier Buzzi
fuente
7

En caso de que esté interesado en una solución que utilice Java 7 y NIO.2, podría ser así:

private static class DirectoriesFilter implements Filter<Path> {
    @Override
    public boolean accept(Path entry) throws IOException {
        return Files.isDirectory(entry);
    }
}

try (DirectoryStream<Path> ds = Files.newDirectoryStream(FileSystems.getDefault().getPath(root), new DirectoriesFilter())) {
        for (Path p : ds) {
            System.out.println(p.getFileName());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
voo
fuente
3
ArrayList<File> directories = new ArrayList<File>(
    Arrays.asList(
        new File("your/path/").listFiles(File::isDirectory)
    )
);
bcangas97
fuente
Hola y bienvenido a StackOverflow. ¿Puedes desarrollar tu respuesta un poco? ¿Le gusta explicar partes interesantes de sus fragmentos de código o vincular a la documentación para leer más?
Richard-Degenne
Esta debería ser la respuesta correcta, ya que proporciona un objeto Archivo con la ruta canónica completa. Esto puede ser antiguo, pero vale la pena señalarlo
Jero Dungog
2

Para aquellos que también estén interesados ​​en Java 7 y NIO, existe una solución alternativa a la respuesta de @ voo anterior . Podemos usar un try-with-resources que llama Files.find()y una función lambda que se usa para filtrar los directorios.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;


final Path directory = Paths.get("/path/to/folder");

try (Stream<Path> paths = Files.find(directory, Integer.MAX_VALUE, (path, attributes) -> attributes.isDirectory())) {
    paths.forEach(System.out::println);
} catch (IOException e) {
    ...
}

Incluso podemos filtrar directorios por nombre cambiando la función lambda:

(path, attributes) -> attributes.isDirectory() && path.toString().contains("test")

o por fecha:

final long now = System.currentTimeMillis();
final long yesterday = new Date(now - 24 * 60 * 60 * 1000L).getTime();

// modified in the last 24 hours
(path, attributes) -> attributes.isDirectory() && attributes.lastModifiedTime().toMillis() > yesterday
HugoTeixeira
fuente
2

Me gustaría usar la funcionalidad java.io.File,

En 2012 (fecha de la pregunta) sí, hoy no. java.nioLa API debe ser favorecida para tales requisitos.

Terrible con tantas respuestas, pero no de la forma simple en que lo usaría Files.walk().filter().collect().

A nivel mundial, son posibles dos enfoques:

1) Files.walk(Path start, )no tiene maxDepthlimitaciones mientras

2) Files.walk(Path start, int maxDepth, FileVisitOption... options)permite configurarlo.

Sin especificar ninguna limitación de profundidad, daría:

Path directory = Paths.get("/foo/bar");

try {
    List<Path> directories =
            Files.walk(directory)
                 .filter(Files::isDirectory)
                 .collect(Collectors.toList());
} catch (IOException e) {
    // process exception
}

Y si por razones heredadas, necesita obtener una lista File, puede agregar una map(Path::toFile)operación antes de la recopilación:

Path directory = Paths.get("/foo/bar");

try {
    List<File> directories =
            Files.walk(directory)
                 .filter(Files::isDirectory)
                 .map(Path::toFile)
                 .collect(Collectors.toList());
} catch (IOException e) {
    // process exception
}
davidxxx
fuente
También hay Files.list(Path)que probablemente sea el mismo que Files.walk(Path,1).
David L.
@David L Indeed Files.list(Path)es una alternativa justa si no queremos iterar carpetas de forma recursiva. Para iterar carpetas de forma recursiva, walk()encaja mejor.
davidxxx
0

Dado un directorio inicial como String

  1. Cree un método que tome una Stringruta como parámetro. En el método:
  2. Cree un nuevo objeto File basado en el directorio de inicio
  3. Obtenga una matriz de archivos en el directorio actual usando el listFilesmétodo
  4. Recorre la matriz de archivos
    1. Si es un archivo, continúa repitiendo
    2. Si es un directorio, imprima el nombre y repita en esta nueva ruta de directorio
Jonathon Faust
fuente
hola, gracias por la respuesta. Pero no tengo que iterar sobre todos los elementos de un directorio. Tengo que enumerar directamente el subdirectorio del directorio. Porque tengo muchos archivos y solo unos pocos subdirectorios en un directorio, por lo que verificar isDirectory () lleva mucho tiempo. por favor respóndeme de otra manera.
Lokesh Paunikar
0

Aquí está la solución para mi código. Acabo de hacer un pequeño cambio desde la primera respuesta . Esto enumerará todas las carpetas solo en el directorio deseado línea por línea:

try {
            File file = new File("D:\\admir\\MyBookLibrary");
            String[] directories = file.list(new FilenameFilter() {
              @Override
              public boolean accept(File current, String name) {
                return new File(current, name).isDirectory();
              }
            });
            for(int i = 0;i < directories.length;i++) {
                if(directories[i] != null) {
                    System.out.println(Arrays.asList(directories[i]));

                }
            }
        }catch(Exception e) {
            System.err.println("Error!");
        }
Tabby Auguste
fuente