0Pricing
Java Academy · Урок

Обход деревьев каталогов с Files.walk

Рекурсивно перечисляйте файлы, фильтруйте их по расширению и вычисляйте размеры каталогов с помощью Files.walk.

«Обход деревьев каталогов с Files.walk» — бесплатный урок Java Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.

Обзор Files.walk

Files.walk(startPath) возвращает ленивый Stream<Path>, который рекурсивно перечисляет все файлы и каталоги, начиная с указанного пути. Обход выполняется в глубину и включает сам начальный путь.

import java.nio.file.*;
import java.util.stream.*;

try (Stream<Path> stream = Files.walk(Path.of("/home/user/projects"))) {
    stream.forEach(System.out::println);
} // stream and underlying resources closed automatically

Ограничение глубины

Укажите максимальную глубину, чтобы предотвратить слишком глубокую рекурсию:

Path root = Path.of("/home/user/projects");

// Only immediate children (depth 1)
try (var stream = Files.walk(root, 1)) {
    stream.filter(p -> !p.equals(root)) // exclude start path
          .forEach(System.out::println);
}

Фильтрация по типу файла

Объедините с Files.isRegularFile() или Files.isDirectory() для фильтрации:

Path root = Path.of(".");

try (var stream = Files.walk(root)) {
    long fileCount = stream
        .filter(Files::isRegularFile)
        .count();
    System.out.println("Files: " + fileCount);
}

Фильтрация по расширению

Поиск всех файлов с определённым расширением:

try (var stream = Files.walk(Path.of("/src"))) {
    List<Path> javaFiles = stream
        .filter(Files::isRegularFile)
        .filter(p -> p.toString().endsWith(".java"))
        .collect(Collectors.toList());
    javaFiles.forEach(System.out::println);
}

Вычисление размера каталога

Суммирование размеров всех файлов в каталоге:

try (var stream = Files.walk(Path.of("/home/user/data"))) {
    long totalBytes = stream
        .filter(Files::isRegularFile)
        .mapToLong(p -> {
            try { return Files.size(p); }
            catch (IOException e) { return 0; }
        })
        .sum();
    System.out.printf("Total: %.2f MB%n", totalBytes / 1_048_576.0);
}

Files.list и Files.walk

Files.list(dir) перечисляет только непосредственное содержимое одного каталога (подобно ls). Files.walk выполняет рекурсивный обход подкаталогов.

// Only immediate children:
try (var stream = Files.list(Path.of("/home/user"))) {
    stream.forEach(System.out::println);
}

Files.find для поиска по атрибутам

Files.find(root, depth, matcher) эффективнее, чем walk+filter, если поиск выполняется по атрибутам файла:

import java.nio.file.attribute.BasicFileAttributes;

try (var stream = Files.find(
        Path.of("/home/user"),
        Integer.MAX_VALUE,
        (p, attrs) -> attrs.isRegularFile() && attrs.size() > 1_000_000
)) {
    stream.forEach(p -> System.out.println("Large file: " + p));
}

Удаление дерева каталогов

Используйте walk + sorted(reversed), чтобы удалить каталог и всё его содержимое (сначала самые глубокие файлы):

Path toDelete = Path.of("/tmp/workdir");
try (var stream = Files.walk(toDelete)) {
    stream.sorted(Comparator.reverseOrder())
          .forEach(p -> {
              try { Files.delete(p); }
              catch (IOException e) { e.printStackTrace(); }
          });
}

Копирование дерева каталогов

Обойдите исходное дерево и скопируйте каждый файл, сохраняя структуру каталогов:

Path src = Path.of("/source"), dst = Path.of("/destination");
try (var stream = Files.walk(src)) {
    stream.forEach(p -> {
        try {
            Path target = dst.resolve(src.relativize(p));
            if (Files.isDirectory(p)) Files.createDirectories(target);
            else Files.copy(p, target, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) { throw new RuntimeException(e); }
    });
}

Обработка недоступных файлов

Files.walk выдаёт IOException, если встречает каталог, который не может прочитать. Используйте FileVisitOption.FOLLOW_LINKS осторожно — циклы символических ссылок могут привести к бесконечной рекурсии.

try (var stream = Files.walk(Path.of("/"),
        FileVisitOption.FOLLOW_LINKS)) { // caution: symlink loops
    // ...
} catch (IOException e) {
    System.err.println("Access error: " + e.getMessage());
}

walkFileTree: событийный обход

Для более точного управления (обработки до и после посещения, обработки ошибок) используйте Files.walkFileTree() с FileVisitor:

Files.walkFileTree(Path.of("/home/user"), new SimpleFileVisitor<Path>() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        System.out.println("File: " + file);
        return FileVisitResult.CONTINUE;
    }
    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        System.out.println("Dir: " + dir);
        return FileVisitResult.CONTINUE;
    }
});

Быстрая проверка

Какой метод Files следует использовать, чтобы перечислить ONLY непосредственные дочерние элементы каталога (без рекурсии)?

Итоги: Files.walk

Основные выводы:

  • Files.walk(root) — рекурсивный ленивый Stream всех путей
  • Всегда используйте try-with-resources, чтобы закрыть поток
  • Фильтруйте с помощью Files.isRegularFile/isDirectory; фильтруйте по расширению с помощью endsWith
  • Files.list(dir) — только непосредственные дочерние элементы
  • Files.find — эффективный поиск по атрибутам
  • walkFileTree — событийный обход с обратными вызовами до и после посещения

Часто задаваемые вопросы

Урок «Обход деревьев каталогов с Files.walk» бесплатный?

Да — полный текст урока «Обход деревьев каталогов с Files.walk» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.

Чему я научусь в уроке «Обход деревьев каталогов с Files.walk»?

Рекурсивно перечисляйте файлы, фильтруйте их по расширению и вычисляйте размеры каталогов с помощью Files.walk. Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Java Academy?

Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Обход деревьев каталогов с Files.walk»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Java Academy?

Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Path: представление расположений файлов
  2. Утилита Files: чтение, запись, копирование и перемещение
  3. Обход деревьев каталогов с Files.walk
  4. WatchService: отслеживание изменений файлов
← Назад к Java Academy