Recursively list files in Java

JavaFileRecursionJava 7Nio

Java Problem Overview


How do I recursively list all files under a directory in Java? Does the framework provide any utility?

I saw a lot of hacky implementations. But none from the framework or nio

Java Solutions


Solution 1 - Java

Java 8 provides a nice stream to process all files in a tree.

Files.walk(Paths.get(path))
        .filter(Files::isRegularFile)
        .forEach(System.out::println);

This provides a natural way to traverse files. Since it's a stream you can do all nice stream operations on the result such as limit, grouping, mapping, exit early etc.

UPDATE: I might point out there is also Files.find which takes a BiPredicate that could be more efficient if you need to check file attributes.

Files.find(Paths.get(path),
           Integer.MAX_VALUE,
           (filePath, fileAttr) -> fileAttr.isRegularFile())
        .forEach(System.out::println);

Note that while the JavaDoc eludes that this method could be more efficient than Files.walk it is effectively identical, the difference in performance can be observed if you are also retrieving file attributes within your filter. In the end, if you need to filter on attributes use Files.find, otherwise use Files.walk, mostly because there are overloads and it's more convenient.

TESTS: As requested I've provided a performance comparison of many of the answers. Check out the Github project which contains results and a test case.

Solution 2 - Java

FileUtils have iterateFiles and listFiles methods. Give them a try. (from http://commons.apache.org/proper/commons-io/">commons-io</a>;)

Edit: You can check here for a benchmark of different approaches. It seems that the commons-io approach is slow, so pick some of the faster ones from here (if it matters)

Solution 3 - Java

// Ready to run

import java.io.File;

public class Filewalker {
    
    public void walk( String path ) {
    
        File root = new File( path );
        File[] list = root.listFiles();
                
        if (list == null) return;

        for ( File f : list ) {
            if ( f.isDirectory() ) {
                walk( f.getAbsolutePath() );
                System.out.println( "Dir:" + f.getAbsoluteFile() );
            }
            else {
                System.out.println( "File:" + f.getAbsoluteFile() );
            }
        }
    }
    	
    public static void main(String[] args) {
        Filewalker fw = new Filewalker();
        fw.walk("c:\\" );
    }
    
}

Solution 4 - Java

Java 7 will have has Files.walkFileTree:

> If you provide a starting point and a file visitor, it will invoke various methods on the file visitor as it walks through the file in the file tree. We expect people to use this if they are developing a recursive copy, a recursive move, a recursive delete, or a recursive operation that sets permissions or performs another operation on each of the files.

There is now an entire Oracle tutorial on this question.

Solution 5 - Java

No external libraries needed.
Returns a Collection so you can do whatever you want with it after the call.

public static Collection<File> listFileTree(File dir) {
	Set<File> fileTree = new HashSet<File>();
    if(dir==null||dir.listFiles()==null){
    	return fileTree;
    }
    for (File entry : dir.listFiles()) {
    	if (entry.isFile()) fileTree.add(entry);
    	else fileTree.addAll(listFileTree(entry));
    }
    return fileTree;
}

Solution 6 - Java

I would go with something like:

public void list(File file) {
	System.out.println(file.getName());
	File[] children = file.listFiles();
	for (File child : children) {
		list(child);
	}
}

The System.out.println is just there to indicate to do something with the file. there is no need to differentiate between files and directories, since a normal file will simply have zero children.

Solution 7 - Java

I prefer using a queue over recursion for this kind of simple traversion:

List<File> allFiles = new ArrayList<File>();
Queue<File> dirs = new LinkedList<File>();
dirs.add(new File("/start/dir/"));
while (!dirs.isEmpty()) {
  for (File f : dirs.poll().listFiles()) {
    if (f.isDirectory()) {
      dirs.add(f);
    } else if (f.isFile()) {
      allFiles.add(f);
    }
  }
}

Solution 8 - Java

just write it yourself using simple recursion:

public List<File> addFiles(List<File> files, File dir)
{
    if (files == null)
        files = new LinkedList<File>();

    if (!dir.isDirectory())
    {
        files.add(dir);
        return files;
    }

    for (File file : dir.listFiles())
        addFiles(files, file);
    return files;
}

Solution 9 - Java

With Java 7 you can use the following class:

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;

public class MyFileIterator extends SimpleFileVisitor<Path>
{
    public MyFileIterator(String path) throws Exception
    {
        Files.walkFileTree(Paths.get(path), this);
    }

    @Override
    public FileVisitResult visitFile(Path file,
            BasicFileAttributes attributes) throws IOException
    {
        System.out.println("File: " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult preVisitDirectory(Path dir,
            BasicFileAttributes attributes) throws IOException
    {
        System.out.println("Dir: " + dir);
        return FileVisitResult.CONTINUE;
    }
}

Solution 10 - Java

This code is ready to run

public static void main(String... args) {
	File[] files = new File("D:/").listFiles();
    if (files != null) 
	   getFiles(files);
}

public static void getFiles(File[] files) {
	for (File file : files) {
		if (file.isDirectory()) {
			getFiles(file.listFiles());
		} else {
			System.out.println("File: " + file);
		}
	}
}

Solution 11 - Java

I think this should do the work:

File dir = new File(dirname);
String[] files = dir.list();

This way you have files and dirs. Now use recursion and do the same for dirs (File class has isDirectory() method).

Solution 12 - Java

In Java 8, we can now use the Files utility to walk a file tree. Very simple.

Files.walk(root.toPath())
      .filter(path -> !Files.isDirectory(path))
      .forEach(path -> System.out.println(path));

Solution 13 - Java

Apart from the recursive traversal one can use a Visitor based approach as well.

Below code is uses Visitor based approach for the traversal.It is expected that the input to the program is the root directory to traverse.

public interface Visitor {
    void visit(DirElement d);
    void visit(FileElement f);
}

public abstract class Element {
    protected File rootPath;
    abstract void accept(Visitor v);

    @Override
    public String toString() {
        return rootPath.getAbsolutePath();
    }
}

public class FileElement extends Element {
    FileElement(final String path) {
        rootPath = new File(path);
    }

    @Override
    void accept(final Visitor v) {
        v.visit(this);
    }
}

public class DirElement extends Element implements Iterable<Element> {
    private final List<Element> elemList;
    DirElement(final String path) {
        elemList = new ArrayList<Element>();
        rootPath = new File(path);
        for (File f : rootPath.listFiles()) {
            if (f.isDirectory()) {
                elemList.add(new DirElement(f.getAbsolutePath()));
            } else if (f.isFile()) {
                elemList.add(new FileElement(f.getAbsolutePath()));
            }
        }
    }

    @Override
    void accept(final Visitor v) {
        v.visit(this);
    }

    public Iterator<Element> iterator() {
        return elemList.iterator();
    }
}

public class ElementWalker {
    private final String rootDir;
    ElementWalker(final String dir) {
        rootDir = dir;
    }

    private void traverse() {
        Element d = new DirElement(rootDir);
        d.accept(new Walker());
    }

    public static void main(final String[] args) {
        ElementWalker t = new ElementWalker("C:\\temp");
        t.traverse();
    }

    private class Walker implements Visitor {
        public void visit(final DirElement d) {
            System.out.println(d);
            for(Element e:d) {
                e.accept(this);
            }
        }

        public void visit(final FileElement f) {
            System.out.println(f);
        }
    }
}

Solution 14 - Java

You can use below code to get a list of files of specific folder or directory recursively.

public static void main(String args[]) {
      
		recusiveList("D:");
		
	}

	public static void recursiveList(String path) {

		File f = new File(path);
		File[] fl = f.listFiles();
		for (int i = 0; i < fl.length; i++) {
			if (fl[i].isDirectory() && !fl[i].isHidden()) {
				System.out.println(fl[i].getAbsolutePath());
				recusiveList(fl[i].getAbsolutePath());
			} else {
				System.out.println(fl[i].getName());
			}
		}
	}

Solution 15 - Java

I came up with this for printing all the files/file names recursively.

private static void printAllFiles(String filePath,File folder) {
	if(filePath==null) {
		return;
	}
	File[] files = folder.listFiles();
	for(File element : files) {
		if(element.isDirectory()) {
			printAllFiles(filePath,element);
		} else {
			System.out.println(" FileName "+ element.getName());
		}
	}
}

Solution 16 - Java

> Lists all files with provided extensions,with option to scan > subfolders (recursive)

 public static ArrayList<File> listFileTree(File dir,boolean recursive) {
        if (null == dir || !dir.isDirectory()) {
            return new ArrayList<>();
        }
        final Set<File> fileTree = new HashSet<File>();
        FileFilter fileFilter = new FileFilter() {
            private final String[] acceptedExtensions = new String[]{"jpg", "png", "webp", "jpeg"};

            @Override
            public boolean accept(File file) {
                if (file.isDirectory()) {
                    return true;
                }
                for (String extension : acceptedExtensions) {
                    if (file.getName().toLowerCase().endsWith(extension)) {
                        return true;
                    }
                }
                return false;
            }
        };
        File[] listed = dir.listFiles(fileFilter);
        if(listed!=null){
            for (File entry : listed) {
                if (entry.isFile()) {
                    fileTree.add(entry);
                } else if(recursive){
                    fileTree.addAll(listFileTree(entry,true));
                }
            }
        }
        return new ArrayList<>(fileTree);
    }

Solution 17 - Java

Non-recursive BFS with a single list (particular example is searching for *.eml files):

    final FileFilter filter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            return file.isDirectory() || file.getName().endsWith(".eml");
        }
    };

    // BFS recursive search
    List<File> queue = new LinkedList<File>();
    queue.addAll(Arrays.asList(dir.listFiles(filter)));

    for (ListIterator<File> itr = queue.listIterator(); itr.hasNext();) {
        File file = itr.next();
        if (file.isDirectory()) {
            itr.remove();
            for (File f: file.listFiles(filter)) itr.add(f);
        }
    }

Solution 18 - Java

My version (of course I could have used the built in walk in Java 8 ;-) ):

public static List<File> findFilesIn(File rootDir, Predicate<File> predicate) {
        ArrayList<File> collected = new ArrayList<>();
        walk(rootDir, predicate, collected);
        return collected;
    }

    private static void walk(File dir, Predicate<File> filterFunction, List<File> collected) {
        Stream.of(listOnlyWhenDirectory(dir))
                .forEach(file -> walk(file, filterFunction, addAndReturn(collected, file, filterFunction)));
    }

    private static File[] listOnlyWhenDirectory(File dir) {
        return dir.isDirectory() ? dir.listFiles() : new File[]{};
    }

    private static List<File> addAndReturn(List<File> files, File toAdd, Predicate<File> filterFunction) {
        if (filterFunction.test(toAdd)) {
            files.add(toAdd);
        }
        return files;
    }

Solution 19 - Java

Here a simple but perfectly working solution using recursion:

public static List<Path> listFiles(String rootDirectory)
{
	List<Path> files = new ArrayList<>();
	listFiles(rootDirectory, files);

	return files;
}

private static void listFiles(String path, List<Path> collectedFiles)
{
	File root = new File(path);
	File[] files = root.listFiles();

	if (files == null)
	{
		return;
	}

	for (File file : files)
	{
		if (file.isDirectory())
		{
			listFiles(file.getAbsolutePath(), collectedFiles);
		} else
		{
			collectedFiles.add(file.toPath());
		}
	}
}

Solution 20 - Java

    private void fillFilesRecursively(File file, List<File> resultFiles) {
        if (file.isFile()) {
            resultFiles.add(file);
        } else {
            for (File child : file.listFiles()) {
                fillFilesRecursively(child, resultFiles);
            }
        }
    }

Solution 21 - Java

Kotlin has FileTreeWalk for this purpose. For example:

dataDir.walkTopDown().filter { !it.isDirectory }.joinToString("\n") {
   "${it.toRelativeString(dataDir)}: ${it.length()}"
}

Will produce a text list of all the non-directory files under a given root, one file per line with the path relative to the root and length.

Solution 22 - Java

The accepted answer is great, however it breaks down when you want to do IO inside the lambda.

Here is what you can do if your action declares IOExceptions.

You can treat the filtered stream as an Iterable, and then do your action in a regular for-each loop. This way, you don't have to handle exceptions inside a lambda.

try (Stream<Path> pathStream = Files.walk(Paths.get(path))
        .filter(Files::isRegularFile)) {

    for (Path file : (Iterable<Path>) pathStream::iterator) {
        // something that throws IOException
        Files.copy(file, System.out);
    }
}

Found that trick here: https://stackoverflow.com/a/32668807/1207791

Solution 23 - Java

Another way you can do even if someone already provide Java 8 walk.

This one will provide you all files recursively

  private Stream<File> files(File file) {
    return file.isDirectory()
            ? Arrays.stream(file.listFiles()).flatMap(this::files)
            : Stream.of(file);
}

Solution 24 - Java

public static String getExten(String path) {
	int i = path.lastIndexOf('.');
	if (i > 0) {
	   return path.substring(i);
	}
	else return "";
}
public static List<String> GetAllFiles(String path, List<String>fileList){
	File file = new File(path);
	
	File[] files = file.listFiles();
	for(File folder:files) {
		if(extensions.contains(getExten(folder.getPath()))) {
			fileList.add(folder.getPath());
		}
	}
	File[] direcs = file.listFiles(File::isDirectory);
	for(File dir:direcs) {
		GetAllFiles(dir.getPath(),fileList);
	}
	return fileList;
	
}

This is a simple recursive function that should give you all the files. extensions is a list of string that contains only those extensions which are accepted. Example extensions = [".txt",".docx"] etc.

Solution 25 - Java

The accepted answer is poor because it can result in a resource leak.

Files.walk is backed by DirectoryStreams.

> The returned stream encapsulates one or more DirectoryStreams. If timely disposal of file system resources is required, the try-with-resources construct should be used to ensure that the stream's close method is invoked after the stream operations are completed. Operating on a closed stream will result in an IllegalStateException.

A DirectoryStream must be closed as specified in it's javadoc:

> A DirectoryStream is opened upon creation and is closed by invoking the close method. Closing a directory stream releases any resources associated with the stream. Failure to close the stream may result in a resource leak. The try-with-resources statement provides a useful construct to ensure that the stream is closed:

Path dir = ...
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
    for (Path entry: stream) {
        ...
    }
}

As a result, the true answer is:

try (Stream<Path> stream = Files.walk(Paths.get(path))) {
    // Do something with the stream.
    stream.filter(Files::isRegularFile)
          .forEach(System.out::println);
}

Solution 26 - Java

List<Path> filePaths = Files
    .find(Paths.get(dir), Integer.MAX_VALUE, (filePath, fileAttr) -> fileAttr.isRegularFile() || fileAttr.isDirectory())
    .collect(Collectors.toList());

filePaths will have files and folder list which can be iterated and proceed further.

Solution 27 - Java

Example outputs *.csv files in directory recursive searching Subdirectories using Files.find() from java.nio:

String path = "C:/Daten/ibiss/ferret/";
    logger.debug("Path:" + path);
    try (Stream<Path> fileList = Files.find(Paths.get(path), Integer.MAX_VALUE,
            (filePath, fileAttr) -> fileAttr.isRegularFile() && filePath.toString().endsWith("csv"))) {
        List<String> someThingNew = fileList.sorted().map(String::valueOf).collect(Collectors.toList());
        for (String t : someThingNew) {
            t.toString();
            logger.debug("Filename:" + t);
        }

    }

Posting this example, as I had trouble understanding howto pass the filename parameter in the #1 example given by Bryan, using foreach on Stream-result -

Hope this helps.

Solution 28 - Java

base on @Michael answer, add check whether listFiles return null

static Stream<File> files(File file) {
    return file.isDirectory()
            ? Optional.ofNullable(file.listFiles()).map(Stream::of).orElseGet(Stream::empty).flatMap(MainActivity::files)
            : Stream.of(file);
}

or use Lightweight-Stream-API, which support Android5 & Android6

static Stream<File> files(File f) {
    return f.isDirectory() ? Stream.ofNullable(f.listFiles()).flatMap(MainActivity::files) : Stream.of(f);
}

Solution 29 - Java

Based on stacker answer. Here is a solution working in JSP without any external libraries so you can put it almost anywhere on your server:

<!DOCTYPE html>
<%@ page session="false" %>
<%@ page import="java.util.*" %>
<%@ page import="java.io.*" %>
<%@ page contentType="text/html; charset=UTF-8" %>

<%!
	public List<String> files = new ArrayList<String>();
	/**
		Fills files array with all sub-files.
	*/
	public void walk( File root ) {
		File[] list = root.listFiles();

		if (list == null) return;

		for ( File f : list ) {
			if ( f.isDirectory() ) {
				walk( f );
			}
			else {
				files.add(f.getAbsolutePath());
			}
		}
	}
%>
<%
	files.clear();
	File jsp = new File(request.getRealPath(request.getServletPath()));
	File dir = jsp.getParentFile();
	walk(dir);
	String prefixPath = dir.getAbsolutePath() + "/";
%>

Then you just do something like:

	<ul>
		<% for (String file : files) { %>
			<% if (file.matches(".+\\.(apk|ipa|mobileprovision)")) { %>
				<li><%=file.replace(prefixPath, "")%></li>
			<% } %>
		<% } %>
	</ul>

Solution 30 - Java

import java.io.File;

public class Main {
	public static void main(String[] args) {
		loopFiles(new File("C:\\Users\\serge.klimkovitch\\Documents"));
	}

	private static void loopFiles(File element) {
		if (element.isDirectory()) {
			for (File currentFile : element.listFiles()) {
				loopFiles(currentFile);
				System.out.println(currentFile);
			}
		}
	}
}

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
QuestionQuintin ParView Question on Stackoverflow
Solution 1 - JavaBrett RyanView Answer on Stackoverflow
Solution 2 - JavaBozhoView Answer on Stackoverflow
Solution 3 - JavastackerView Answer on Stackoverflow
Solution 4 - JavayawnView Answer on Stackoverflow
Solution 5 - JavaPetrucioView Answer on Stackoverflow
Solution 6 - JavaStefan SchmidtView Answer on Stackoverflow
Solution 7 - JavabenrothView Answer on Stackoverflow
Solution 8 - JavapstantonView Answer on Stackoverflow
Solution 9 - JavachaoView Answer on Stackoverflow
Solution 10 - JavaEbraheem AlrabeeaView Answer on Stackoverflow
Solution 11 - JavaMichał NiklasView Answer on Stackoverflow
Solution 12 - JavaRoy KachouhView Answer on Stackoverflow
Solution 13 - JavasateeshView Answer on Stackoverflow
Solution 14 - JavaRakesh ChaudhariView Answer on Stackoverflow
Solution 15 - JavakanaparthikiranView Answer on Stackoverflow
Solution 16 - JavaOmkar TView Answer on Stackoverflow
Solution 17 - JavabobahView Answer on Stackoverflow
Solution 18 - Javauser1189332View Answer on Stackoverflow
Solution 19 - JavaBullyWiiPlazaView Answer on Stackoverflow
Solution 20 - JavalegendmoheView Answer on Stackoverflow
Solution 21 - JavaClydeView Answer on Stackoverflow
Solution 22 - JavacfstrasView Answer on Stackoverflow
Solution 23 - JavaMichaelView Answer on Stackoverflow
Solution 24 - JavaParikshit PhukanView Answer on Stackoverflow
Solution 25 - JavajosephView Answer on Stackoverflow
Solution 26 - JavaSaravanan AndavarView Answer on Stackoverflow
Solution 27 - JavaRalf R.View Answer on Stackoverflow
Solution 28 - JavaYessyView Answer on Stackoverflow
Solution 29 - JavaNuxView Answer on Stackoverflow
Solution 30 - JavasklimkovitchView Answer on Stackoverflow