Java, Nur Unterverzeichnisse aus einem Verzeichnis auflisten, keine Dateien

100

Wie liste ich in Java nur Unterverzeichnisse aus einem Verzeichnis auf?

Ich möchte die Funktion java.io.File verwenden. Was ist die beste Methode in Java, um dies zu tun?

Lokesh Paunikar
quelle

Antworten:

140

Mit der File- Klasse können Sie die Verzeichnisse auflisten.

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

Aktualisieren

Kommentar des Autors zu diesem Beitrag wollte einen schnelleren Weg, tolle Diskussion hier: Wie kann man eine Liste von Verzeichnissen SCHNELL in Java abrufen?

Grundsätzlich:

  1. Wenn Sie die Dateistruktur steuern, würde ich versuchen, nicht in diese Situation zu geraten.
  2. In Java NIO.2 können Sie die Verzeichnisfunktion verwenden, um einen Iterator zurückzugeben, um eine größere Skalierung zu ermöglichen. Die Verzeichnisstromklasse ist ein Objekt, mit dem Sie die Einträge in einem Verzeichnis durchlaufen können.
Mohamed Mansour
quelle
Hallo, danke für die Antwort. Aber ich muss nicht alle Elemente in einem Verzeichnis durchlaufen. Ich muss das Unterverzeichnis direkt aus dem Verzeichnis auflisten. B'coz Ich habe viele Dateien und nur wenige Unterverzeichnisse in einem Verzeichnis, daher ist das Überprüfen von isDirectory () zeitaufwändig. Bitte antworte mir anders.
Lokesh Paunikar
Ich habe meinen Beitrag aktualisiert, insbesondere einen Blick auf Jon Skeets Kommentar zu der Frage. Und die NIO-Antwort seit Java NIO 2 verfügt über einen Iterator für die Verzeichnisfunktion, der einen Strom von Verzeichnissen zurückgibt.
Mohamed Mansour
Auf welchen Skeet-Kommentar beziehen Sie sich? Was ist hier die Antwort mit der besseren Leistung?
Stealth Rabbi
107

Eine sehr einfache Java 8-Lösung:

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

Dies entspricht der Verwendung eines FileFilter (funktioniert auch mit älterem Java):

File[] directories = new File("/your/path/").listFiles(new FileFilter() {
    @Override
    public boolean accept(File file) {
        return file.isDirectory();
    }
});
Headsvk
quelle
4
Wie funktioniert der Doppelpunkt ::in diesem Fall?
snickers10m
Ich habe festgestellt, dass keine andere Antwort FileFilter verwendet, daher habe ich die entsprechende Version hinzugefügt, ohne Methodenreferenzen zu verwenden. Weitere Informationen zu Methodenreferenzen finden Sie in dieser SO-Frage oder in diesem Artikel .
Headsvk
Erhält dies Unterverzeichnisse oder nur die Verzeichnisse direkt unter / your / path /?
Amadain
@amadain keine Rekursion wie erwartet docs.oracle.com/javase/7/docs/api/java/io/File.html#listFiles ()
Headsvk
14

@Mohamed Mansour du warst fast da ... das "dir" Argument, das du benutzt hast, ist eigentlich der aktuelle Pfad, also wird es immer true zurückgeben. Um festzustellen, ob das Kind ein Unterverzeichnis ist oder nicht, müssen Sie dieses Kind testen.

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

Wenn Sie an einer Lösung mit Java 7 und NIO.2 interessiert sind, könnte dies folgendermaßen aussehen:

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
quelle
3
ArrayList<File> directories = new ArrayList<File>(
    Arrays.asList(
        new File("your/path/").listFiles(File::isDirectory)
    )
);
bcangas97
quelle
Hallo und willkommen bei StackOverflow! Können Sie Ihre Antwort etwas näher erläutern? Sie möchten interessante Teile Ihrer Codefragmente erklären oder zum weiteren Lesen auf die Dokumentation verlinken?
Richard-Degenne
Dies sollte die richtige Antwort sein, da ein Dateiobjekt den vollständigen kanonischen Pfad enthält. Das mag alt sein, aber es lohnt sich darauf hinzuweisen
Jero Dungog
2

Für diejenigen, die sich auch für Java 7 und NIO interessieren, gibt es eine alternative Lösung zu der obigen Antwort von @ voo . Wir können einen Try-with-Resources- Aufruf verwenden Files.find()und eine Lambda-Funktion, mit der die Verzeichnisse gefiltert werden.

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) {
    ...
}

Wir können Verzeichnisse sogar nach Namen filtern, indem wir die Lambda-Funktion ändern:

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

oder nach Datum:

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
quelle
2

Ich möchte die Funktionalität java.io.File verwenden.

Im Jahr 2012 (Datum der Frage) ja, nicht heute. java.nioAPI muss für solche Anforderungen bevorzugt werden.

Schrecklich mit so vielen Antworten, aber nicht so einfach, wie ich das verwenden würde Files.walk().filter().collect().

Global sind zwei Ansätze möglich:

1) Files.walk(Path start, )hat keine maxDepthEinschränkungen während

2) Files.walk(Path start, int maxDepth, FileVisitOption... options)erlaubt es einzustellen.

Ohne Angabe einer Tiefenbeschränkung würde dies Folgendes ergeben:

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

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

Und wenn Sie aus alten Gründen eine Liste benötigen, Filekönnen Sie map(Path::toFile)vor dem Sammeln einfach eine Operation hinzufügen :

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
quelle
Es gibt auch Files.list(Path)was wohl das gleiche ist wie Files.walk(Path,1).
David L.
@ David L In der Tat Files.list(Path)ist eine faire Alternative, wenn wir keine rekursiven Ordner iterieren möchten. Ordner rekursiv zu iterieren, walk()passt besser.
Davidxxx
1

Die Lösung, die für mich funktioniert hat, fehlt in der Liste der Antworten. Daher poste ich diese Lösung hier:

File[]dirs = new File("/mypath/mydir/").listFiles((FileFilter)FileFilterUtils.directoryFileFilter());

Hier habe ich org.apache.commons.io.filefilter.FileFilterUtilsvon Apache commons-io-2.2.jar verwendet. Die Dokumentation finden Sie hier: https://commons.apache.org/proper/commons-io/javadocs/api-2.2/org/apache/commons/io/filefilter/FileFilterUtils.html

Abhishek Oza
quelle
0

Gegeben ein Startverzeichnis als String

  1. Erstellen Sie eine Methode, die einen StringPfad als Parameter verwendet. In der Methode:
  2. Erstellen Sie ein neues Dateiobjekt basierend auf dem Startverzeichnis
  3. Rufen Sie mit der listFilesMethode ein Array von Dateien im aktuellen Verzeichnis ab
  4. Durchlaufen Sie das Array von Dateien
    1. Wenn es sich um eine Datei handelt, fahren Sie mit der Schleife fort
    2. Wenn es sich um ein Verzeichnis handelt, drucken Sie den Namen aus und verwenden Sie diesen neuen Verzeichnispfad
Jonathon Faust
quelle
Hallo, danke für die Antwort. Aber ich muss nicht alle Elemente in einem Verzeichnis durchlaufen. Ich muss das Unterverzeichnis direkt aus dem Verzeichnis auflisten. B'coz Ich habe viele Dateien und nur wenige Unterverzeichnisse in einem Verzeichnis, daher ist das Überprüfen von isDirectory () zeitaufwändig. Bitte antworte mir anders.
Lokesh Paunikar
0

Hier ist eine Lösung für meinen Code. Ich habe gerade eine kleine Änderung von der ersten Antwort gemacht . Dadurch werden alle Ordner zeilenweise nur im gewünschten Verzeichnis aufgelistet:

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
quelle