Java, wyświetla tylko podkatalogi z katalogu, a nie pliki

100

W Javie, jak wyświetlić tylko podkatalogi z katalogu?

Chciałbym skorzystać z funkcjonalności java.io.File. Jaka jest najlepsza metoda w Javie, aby to zrobić?

Lokesh Paunikar
źródło

Odpowiedzi:

141

Możesz użyć klasy File, aby wyświetlić listę katalogów.

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

Aktualizacja

Komentarz autora do tego postu chciał szybszego sposobu, świetna dyskusja tutaj: Jak szybko pobrać listę katalogów w Javie?

Gruntownie:

  1. Jeśli kontrolujesz strukturę plików, starałbym się uniknąć takiej sytuacji.
  2. W Javie NIO.2 można użyć funkcji katalogów, aby zwrócić iterator, aby umożliwić większe skalowanie. Klasa strumienia katalogu to obiekt, którego można używać do iteracji po wpisach w katalogu.
Mohamed Mansour
źródło
cześć, dziękuję za odpowiedź. Ale nie muszę iterować po wszystkich elementach w katalogu. Muszę bezpośrednio wyświetlić podkatalog z katalogu. B'coz Mam dużo plików i tylko kilka podkatalogów w katalogu, więc sprawdzenie isDirectory () jest czasochłonne. proszę, odpowiedz mi w inny sposób.
Lokesh Paunikar
Zaktualizowałem swój post, w szczególności spójrz na komentarz Jona Skeeta do pytania. A odpowiedź NIO, ponieważ Java NIO 2 ma iterator dla funkcji katalogów, która zwraca strumień katalogów.
Mohamed Mansour,
Jaki komentarz Skeet masz na myśli? Jaka jest tutaj lepsza odpowiedź?
Stealth Rabbi
107

Bardzo proste rozwiązanie Java 8:

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

Jest to równoważne użyciu FileFilter (działa również ze starszą Javą):

File[] directories = new File("/your/path/").listFiles(new FileFilter() {
    @Override
    public boolean accept(File file) {
        return file.isDirectory();
    }
});
headsvk
źródło
4
Jak działa podwójny dwukropek ::w tym przypadku?
snickers 10 min
Zauważyłem, że żadna inna odpowiedź nie używa FileFilter, więc dodałem równoważną wersję bez użycia odwołań do metod. Więcej informacji na temat odwołań do metod można znaleźć w tym pytaniu SO lub w tym artykule .
Headsvk
czy to pobiera podkatalogi czy tylko katalogi bezpośrednio w / twoja / ścieżka /?
amadain
@amadain bez rekursji zgodnie z oczekiwaniami docs.oracle.com/javase/7/docs/api/java/io/File.html#listFiles ()
headsvk
14

@Mohamed Mansour, prawie byłeś ... argument "dir", którego używałeś, jest w rzeczywistości aktualną ścieżką, więc zawsze zwróci prawdę. Aby sprawdzić, czy dziecko jest podkatalogiem, czy nie, musisz je przetestować.

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
źródło
7

Jeśli jesteś zainteresowany rozwiązaniem wykorzystującym Javę 7 i NIO.2, może to wyglądać tak:

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
źródło
3
ArrayList<File> directories = new ArrayList<File>(
    Arrays.asList(
        new File("your/path/").listFiles(File::isDirectory)
    )
);
bcangas97
źródło
Cześć i witaj w StackOverflow! Czy możesz trochę rozwinąć swoją odpowiedź? Lubisz wyjaśniać interesujące części fragmentów kodu lub linkować do dokumentacji w celu dalszego czytania?
Richard-Degenne
Powinna to być poprawna odpowiedź, ponieważ zapewnia obiektowi File z pełną ścieżką kanoniczną. To może być stare, ale warto na to zwrócić uwagę
Jero Dungog
2

Dla tych, którzy są również zainteresowani Javą 7 i NIO, istnieje alternatywne rozwiązanie powyższej odpowiedzi @ voo . Możemy użyć wywołania try-with-resourcesFiles.find() i funkcji lambda, która jest używana do filtrowania katalogów.

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

Możemy nawet filtrować katalogi według nazwy, zmieniając funkcję lambda:

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

lub według daty:

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
źródło
2

Chciałbym skorzystać z funkcjonalności java.io.File,

W 2012 roku (data zapytania) tak, nie dzisiaj. java.nioW przypadku takich wymagań należy preferować API.

Okropne z tak wieloma odpowiedziami, ale nie w prosty sposób, w jaki bym tego użył Files.walk().filter().collect().

Globalnie możliwe są dwa podejścia:

1) Files.walk(Path start, )nie ma żadnych maxDepthograniczeń

2) Files.walk(Path start, int maxDepth, FileVisitOption... options)pozwala to ustawić.

Bez określenia ograniczeń głębokości dałoby:

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

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

A jeśli z powodów przestarzałych potrzebujesz uzyskać Listę File, możesz po prostu dodać map(Path::toFile)operację przed kolekcją:

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
źródło
Jest też Files.list(Path)prawdopodobnie to samo co Files.walk(Path,1).
David L.
@David L Rzeczywiście Files.list(Path)jest uczciwą alternatywą, jeśli nie chcemy iterować rekurencyjnie folderów. Aby iterować foldery rekurencyjnie, walk()lepiej pasuje.
davidxxx
1

Na liście odpowiedzi brakuje rozwiązania, które u mnie zadziałało. Dlatego zamieszczam tutaj to rozwiązanie:

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

Tutaj użyłem org.apache.commons.io.filefilter.FileFilterUtilsz Apache commons-io-2.2.jar. Jego dokumentacja jest dostępna tutaj: https://commons.apache.org/proper/commons-io/javadocs/api-2.2/org/apache/commons/io/filefilter/FileFilterUtils.html

Abhishek Oza
źródło
0

Biorąc pod uwagę katalog początkowy jako plik String

  1. Utwórz metodę, która przyjmuje Stringścieżkę jako parametr. W metodzie:
  2. Utwórz nowy obiekt File na podstawie katalogu startowego
  3. Pobierz tablicę plików w bieżącym katalogu przy użyciu listFilesmetody
  4. Zapętlaj tablicę plików
    1. Jeśli to plik, kontynuuj zapętlanie
    2. Jeśli jest to katalog, wydrukuj nazwę i powtórz w tej nowej ścieżce katalogu
Jonathon Faust
źródło
cześć, dziękuję za odpowiedź. Ale nie muszę iterować po wszystkich elementach w katalogu. Muszę bezpośrednio wyświetlić podkatalog z katalogu. B'coz Mam dużo plików i tylko kilka podkatalogów w katalogu, więc sprawdzenie isDirectory () jest czasochłonne. proszę, odpowiedz mi w inny sposób.
Lokesh Paunikar
0

Oto rozwiązanie dla mojego kodu. Zrobiłem tylko małą zmianę od pierwszej odpowiedzi . Spowoduje to wyświetlenie wszystkich folderów tylko w wybranym katalogu wiersz po wierszu:

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
źródło