How do I iterate through the files in a directory and it's sub-directories in Java?

Java

Java Problem Overview


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?

Java Solutions


Solution 1 - Java

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

Solution 2 - Java

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

}

Solution 3 - Java

Check out the FileUtils class in Apache Commons - specifically iterateFiles:

> Allows iteration over the files in given directory (and optionally its subdirectories).

Solution 4 - Java

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.

Solution 5 - Java

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

Solution 6 - Java

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.

Solution 7 - Java

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.

Solution 8 - Java

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

Solution 9 - Java

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

Solution 10 - Java

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:

  1. handle the case of empty directory
  2. 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>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJamesView Question on Stackoverflow
Solution 1 - JavaBalusCView Answer on Stackoverflow
Solution 2 - JavaclstrfsckView Answer on Stackoverflow
Solution 3 - JavaBen JView Answer on Stackoverflow
Solution 4 - JavafjkjavaView Answer on Stackoverflow
Solution 5 - JavaWim DeblauweView Answer on Stackoverflow
Solution 6 - JavaduffymoView Answer on Stackoverflow
Solution 7 - JavaChimmyView Answer on Stackoverflow
Solution 8 - JavaRob KlinkhamerView Answer on Stackoverflow
Solution 9 - JavaRaghu DVView Answer on Stackoverflow
Solution 10 - JavaChamlalView Answer on Stackoverflow