Обход деревьев каталогов с 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 — локальная установка не требуется.
Все уроки этого курса
- Path: представление расположений файлов
- Утилита Files: чтение, запись, копирование и перемещение
- Обход деревьев каталогов с Files.walk
- WatchService: отслеживание изменений файлов