Java, выводить список только подкаталогов из каталога, а не файлов

100

Как в Java перечислить только подкаталоги из каталога?

Я хотел бы использовать функциональность java.io.File, какой метод в Java лучше всего подходит для этого?

Локеш Пауникар
источник

Ответы:

141

Вы можете использовать класс File для вывода списка каталогов.

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

Обновить

Комментарий автора к этому сообщению требует более быстрого способа, отличного обсуждения здесь: Как БЫСТРО получить список каталогов в Java?

В принципе:

  1. Если вы контролируете файловую структуру, я бы постарался избежать такой ситуации.
  2. В Java NIO.2 вы можете использовать функцию каталогов, чтобы вернуть итератор, чтобы обеспечить большее масштабирование. Класс потока каталога - это объект, который можно использовать для перебора записей в каталоге.
Мохамед Мансур
источник
привет спасибо за ответ. Но мне не нужно перебирать все элементы в каталоге. Мне нужно напрямую указать подкаталог из каталога. B'coz У меня много файлов и только несколько подкаталогов в каталоге, поэтому проверка isDirectory () отнимает много времени. пожалуйста, ответьте мне другим способом.
Локеш Пауникар
Я обновил свой пост, в частности, взглянул на комментарий Джона Скита по этому вопросу. И ответ NIO, поскольку в Java NIO 2 есть итератор для функции каталогов, которая возвращает поток каталогов.
Мохамед Мансур
Какой комментарий Скита вы имеете в виду? Какой ответ здесь лучше?
Stealth Rabbi
107

Очень простое решение для Java 8:

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

Это эквивалентно использованию FileFilter (работает и со старой версией Java):

File[] directories = new File("/your/path/").listFiles(new FileFilter() {
    @Override
    public boolean accept(File file) {
        return file.isDirectory();
    }
});
Headsvk
источник
4
Как работает двойное двоеточие ::в этом случае?
snickers10m
Я заметил, что ни один другой ответ не использует FileFilter, поэтому я добавил эквивалентную версию без использования ссылок на методы. Дополнительные сведения о ссылках на методы см. В этом вопросе SO или в этой статье .
HeadSvk 02
получает ли это подкаталоги или только каталоги непосредственно в / your / path /?
amadain
@amadain нет рекурсии, как ожидалось docs.oracle.com/javase/7/docs/api/java/io/File.html#listFiles ()
Headsvk
14

@Mohamed Mansour, вы почти были там ... аргумент "dir" из того, что вы использовали, на самом деле является текущим путем, поэтому он всегда будет возвращать истину. Чтобы увидеть, является ли дочерний каталог подкаталогом или нет, вам нужно протестировать его.

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));
Хавьер Буцци
источник
7

Если вас интересует решение с использованием Java 7 и NIO.2, оно может выглядеть следующим образом:

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();
    }
ву
источник
3
ArrayList<File> directories = new ArrayList<File>(
    Arrays.asList(
        new File("your/path/").listFiles(File::isDirectory)
    )
);
Беатрис Кангас - Перес
источник
Привет и добро пожаловать в StackOverflow! Не могли бы вы немного уточнить свой ответ? Нравится объяснять интересные части фрагментов кода или ссылаться на документацию для дальнейшего чтения?
Richard-Degenne
Это должен быть правильный ответ, поскольку он предоставляет объекту File полный канонический путь. Это может быть старым, но на это стоит обратить внимание
Джеро Дунгог
3

Я хотел бы использовать функциональность java.io.File,

В 2012 году (дата вопроса) да, не сегодня. java.nioДля таких требований следует отдавать предпочтение API.

Ужасно с таким количеством ответов, но не так просто, как я бы это использовал Files.walk().filter().collect().

В глобальном масштабе возможны два подхода:

1) Files.walk(Path start, )не имеет maxDepthограничений, пока

2) Files.walk(Path start, int maxDepth, FileVisitOption... options)позволяет установить его.

Без указания каких-либо ограничений глубины это даст:

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

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

И если по устаревшим причинам вам нужно получить список, Fileвы можете просто добавить map(Path::toFile)операцию перед сбором:

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
источник
Также Files.list(Path)есть, вероятно, то же самое, что и Files.walk(Path,1).
Дэвид Л.
@David L Действительно Files.list(Path), это справедливая альтернатива, если мы не хотим рекурсивно перебирать папки. Для рекурсивной итерации папок walk()подходит лучше.
davidxxx,
2

Для тех, кто также интересуется Java 7 и NIO, есть альтернативное решение для ответа @ voo выше . Мы можем использовать вызывающую команду try-with-resourcesFiles.find() и лямбда-функцию, которая используется для фильтрации каталогов.

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

Мы даже можем фильтровать каталоги по имени, изменив лямбда-функцию:

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

или по дате:

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
источник
1

Решение, которое сработало для меня, отсутствует в списке ответов. Поэтому я публикую это решение здесь:

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

Здесь я использовал org.apache.commons.io.filefilter.FileFilterUtilsApache commons-io-2.2.jar. Его документация доступна здесь: https://commons.apache.org/proper/commons-io/javadocs/api-2.2/org/apache/commons/io/filefilter/FileFilterUtils.html.

Абхишек Оза
источник
0

Учитывая начальный каталог как String

  1. Создайте метод, который принимает Stringпуть в качестве параметра. В методе:
  2. Создайте новый объект File на основе начального каталога
  3. Получить массив файлов в текущем каталоге с помощью listFilesметода
  4. Перебрать массив файлов
    1. Если это файл, продолжайте цикл
    2. Если это каталог, распечатайте имя и перейдите по этому новому пути к каталогу.
Джонатон Фауст
источник
привет спасибо за ответ. Но мне не нужно перебирать все элементы в каталоге. Мне нужно напрямую указать подкаталог из каталога. B'coz У меня много файлов и только несколько подкаталогов в каталоге, поэтому проверка isDirectory () отнимает много времени. пожалуйста, ответьте мне другим способом.
Локеш Пауникар
0

Вот решение для моего кода. Я только что немного изменил свой первый ответ . Это отобразит все папки только в желаемом каталоге построчно:

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!");
        }
Табби Огюст
источник
0

Вы можете использовать API файлов JAVA 7

Path myDirectoryPath = Paths.get("path to my directory");
List<Path> subDirectories = Files.find(
                    myDirectoryPath ,
                    Integer.MAX_VALUE,
                    (filePath, fileAttr) -> fileAttr.isDirectory() && !filePath.equals(myDirectoryPath )
            ).collect(Collectors.toList());

Если вам нужно конкретное значение, вы можете вызвать карту с нужным значением перед сбором данных.

Абдельмогите Мадих
источник