I need to get a list of all the files in a directory, including files in all the sub-directories. What is the standard way to accomplish directory iteration with Java?
10 Answers
You can use File#isDirectory()
to test if the given file (path) is a directory. If this is true
, then you just call the same method again with its File#listFiles()
outcome. This is called recursion.
Here's a basic kickoff example:
package com.stackoverflow.q3154488;
import java.io.File;
public class Demo {
public static void main(String... args) {
File dir = new File("/path/to/dir");
showFiles(dir.listFiles());
}
public static void showFiles(File[] files) {
for (File file : files) {
if (file.isDirectory()) {
System.out.println("Directory: " + file.getAbsolutePath());
showFiles(file.listFiles()); // Calls same method again.
} else {
System.out.println("File: " + file.getAbsolutePath());
}
}
}
}
Note that this is sensitive to StackOverflowError
when the tree is deeper than the JVM's stack can hold. If you're already on Java 8 or newer, then you'd better use Files#walk()
instead which utilizes tail recursion:
package com.stackoverflow.q3154488;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class DemoWithJava8 {
public static void main(String... args) throws Exception {
Path dir = Paths.get("/path/to/dir");
Files.walk(dir).forEach(path -> showFile(path.toFile()));
}
public static void showFile(File file) {
if (file.isDirectory()) {
System.out.println("Directory: " + file.getAbsolutePath());
} else {
System.out.println("File: " + file.getAbsolutePath());
}
}
}

- 1,082,665
- 372
- 3,610
- 3,555
-
thanks Balus, any idea on how deep that may be as a general guess? – James Jul 01 '10 at 02:56
-
11Depends on your JVM's memory settings. But generally something like a few thousand. If you think you might ever run into a directory like that, then don't use recursion. – Mike Baranczak Jul 01 '10 at 04:06
-
4This is susceptible to a `NullPointerException` when the file system changes between the call to `isDirectory` and `listFiles` as might happen if `System.out.println` blocks or you just get really unlucky. Checking that the output of `listFiles` is not null would solve that race condition. – Mike Samuel Apr 20 '14 at 18:00
-
@MikeSamuel - If the directory has 10's of thousands of small files with big names, and you store all file names in an array at once, then JVM could run out of memory, right ? So, is there a way to iterate one by one or in small batches ? – Erran Morad Oct 05 '14 at 01:03
-
1@BoratSagdiyev, Not using the old Java file APIs, but if you're on a modern JVM then the [`java.nio.file.DirectoryStream`](http://docs.oracle.com/javase/7/docs/api/java/nio/file/DirectoryStream.html) allows you to iterate over a directory, and could be implemented to have a small memory footprint but the only way to tell for sure would be to monitor memory usage on a particular platform. – Mike Samuel Oct 05 '14 at 03:14
-
Regarding the comment for usage of `DirectoryStream` please refer to the answer of Wim Deblauwe as it lists important aspect. The stream should be closed to prevent resource leak. – Svilen Jan 29 '20 at 14:25
If you are using Java 1.7, you can use java.nio.file.Files.walkFileTree(...)
.
For example:
public class WalkFileTreeExample {
public static void main(String[] args) {
Path p = Paths.get("/usr");
FileVisitor<Path> fv = new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
System.out.println(file);
return FileVisitResult.CONTINUE;
}
};
try {
Files.walkFileTree(p, fv);
} catch (IOException e) {
e.printStackTrace();
}
}
}
If you are using Java 8, you can use the stream interface with java.nio.file.Files.walk(...)
:
public class WalkFileTreeExample {
public static void main(String[] args) {
try (Stream<Path> paths = Files.walk(Paths.get("/usr"))) {
paths.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
}
-
2is there a way with the streams to put a checkpoint when a new directory is walked and execute a function? – Raghu DV Dec 26 '17 at 15:03
-
`Files.walk(somePath)` will walk you through the whole file and directory tree accessible from that root directory. If you need to process only certain files, i.e. by their extension, you can use a `filter` with `PathMatcher` that you configured to `glob:**.xml` i.e. to omit any non-XML files in later stages of the pipeline – Roman Vottner Feb 04 '21 at 13:47
Check out the FileUtils class in Apache Commons - specifically iterateFiles:
Allows iteration over the files in given directory (and optionally its subdirectories).
-
5This API isn't truly streaming (if you care about mem usage), it first generate a collection, only then returns an iterator over it: return listFiles(directory, fileFilter, dirFilter).iterator(); – Gili Nachum Nov 29 '13 at 16:28
-
-
Agree with @GiliNachum. FileUtils by Apache first collects all files and gives an iterator for them. It is harmful for resources if you have a huge amount of files. – Bogdan Samondros Feb 18 '19 at 14:18
Using org.apache.commons.io.FileUtils
File file = new File("F:/Lines");
Collection<File> files = FileUtils.listFiles(file, null, true);
for(File file2 : files){
System.out.println(file2.getName());
}
Use false if you do not want files from sub directories.
For Java 7+, there is also https://docs.oracle.com/javase/7/docs/api/java/nio/file/DirectoryStream.html
Example taken from the Javadoc:
List<Path> listSourceFiles(Path dir) throws IOException {
List<Path> result = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.{c,h,cpp,hpp,java}")) {
for (Path entry: stream) {
result.add(entry);
}
} catch (DirectoryIteratorException ex) {
// I/O error encounted during the iteration, the cause is an IOException
throw ex.getCause();
}
return result;
}

- 25,113
- 20
- 133
- 211
It's a tree, so recursion is your friend: start with the parent directory and call the method to get an array of child Files. Iterate through the child array. If the current value is a directory, pass it to a recursive call of your method. If not, process the leaf file appropriately.

- 305,152
- 44
- 369
- 561
As noted, this is a recursion problem. In particular, you may want to look at
listFiles()
In the java File API here. It returns an array of all the files in a directory. Using this along with
isDirectory()
to see if you need to recurse further is a good start.

- 10,892
- 14
- 65
- 119

- 112
- 1
- 5
-
This [link](https://docs.oracle.com/javase/8/docs/api/java/io/File.html) may be of use since the one in the answer is broken. – Donglecow Jun 07 '17 at 09:43
You can also misuse File.list(FilenameFilter) (and variants) for file traversal. Short code and works in early java versions, e.g:
// list files in dir
new File(dir).list(new FilenameFilter() {
public boolean accept(File dir, String name) {
String file = dir.getAbsolutePath() + File.separator + name;
System.out.println(file);
return false;
}
});

- 11
- 2
To add with @msandiford answer, as most of the times when a file tree is walked u may want to execute a function as a directory or any particular file is visited. If u are reluctant to using streams. The following methods overridden can be implemented
Files.walkFileTree(Paths.get(Krawl.INDEXPATH), EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
throws IOException {
// Do someting before directory visit
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
// Do something when a file is visited
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
throws IOException {
// Do Something after directory visit
return FileVisitResult.CONTINUE;
}
});

- 258
- 5
- 18
I like to use Optional and streams to have a net and clear solution, i use the below code to iterate over a directory. the below cases are handled by the code:
- handle the case of empty directory
- Laziness
but as mentioned by others, you still have to pay attention for outOfMemory in case you have huge folders
File directoryFile = new File("put your path here");
Stream<File> files = Optional.ofNullable(directoryFile// directoryFile
.listFiles(File::isDirectory)) // filter only directories(change with null if you don't need to filter)
.stream()
.flatMap(Arrays::stream);// flatmap from Stream<File[]> to Stream<File>

- 156
- 1
- 5