This article shows how to Java 8 Files.walk to walk a file tree and stream operation filter to find files that match a specific file extension from a folder and its subfolders.

  // find files matched `png` file extension from folder C:\\test
  try (Stream<Path> walk = Files.walk(Paths.get("C:\\test"))) {
      result = walk
              .filter(p -> !Files.isDirectory(p))   // not a directory
              .map(p -> p.toString().toLowerCase()) // convert path to string
              .filter(f -> f.endsWith("png"))       // check end with
              .collect(Collectors.toList());        // collect all matched to a List
  }

In the Files.walk method, the second argument, maxDepth defined the maximum number of directory levels to visit. And we can assign maxDepth = 1 to find files from the top-level folder only (exclude all its subfolders)

  try (Stream<Path> walk = Files.walk(Paths.get("C:\\test"), 1)) {
      //...
  }

1. Find files with a specified file extension

This example finds files matched with png file extension. The finds start at the top-level folder C:\\test and included all levels of subfolders.

FindFileByExtension1.java

package com.favtuts.io.howto;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FindFileByExtension {
    
    public static void main(String[] args) {
        try {
            List<String> files = findFiles(Paths.get("/home/tvt/workspace/favtuts"), "png");
            files.forEach(x -> System.out.println(x));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static List<String> findFiles(Path path, String fileExtension) throws IOException {

        if (!Files.isDirectory(path)) {
            throw new IllegalArgumentException("Path must be a directory!");
        }

        List<String> result;

        try (Stream<Path> walk = Files.walk(path)) {
            result = walk
                .filter(p -> !Files.isDirectory(p))
                // this is a path, not string,
                // this only test if path end with a certain path
                //.filter(p -> p.endsWith(fileExtension))
                // convert path to string first
                .map(p -> p.toString().toLowerCase())
                .filter(f -> f.endsWith(fileExtension))
                .collect(Collectors.toList());
        }

        return result;        
    }
}

Output

/home/tvt/workspace/favtuts/data/resize-default.png
/home/tvt/workspace/favtuts/google.png
/home/tvt/workspace/favtuts/folder/logo-new.png

2. Find files with multiple file extensions

This example finds files matched with multiple file extensions (.png.jpg.gif).

FindFileByExtension2.java

package com.favtuts.io.howto;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FindFileByExtension {
    
    public static void main(String[] args) {
        try {
 
            String[] fileExtensions = {"png", "jpg", "gif"};
            List<String> files = findFiles(Paths.get(folderName), fileExtensions);
            files.forEach(x -> System.out.println(x));

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static List<String> findFiles(Path path, String[] fileExtensions) throws IOException {

        if (!Files.isDirectory(path)) {
            throw new IllegalArgumentException("Path must be a directory!");
        }

        List<String> result;
        //try (Stream<Path> walk = Files.walk(path, 1)) {
        try (Stream<Path> walk = Files.walk(path)) {
            result = walk
                    .filter(p -> !Files.isDirectory(p))
                    // convert path to string
                    .map(p -> p.toString().toLowerCase())
                    .filter(f -> isEndWith(f, fileExtensions))
                    .collect(Collectors.toList());
        }
        return result;

    }

    private static boolean isEndWith(String file, String[] fileExtensions) {
        boolean result = false;
        //System.out.println("Checking " + file + " ...");
        for (String fileExtension : fileExtensions) {            
            if (file.endsWith(fileExtension)) {
                result = true;
                break;
            }
        }
        return result;
    }
}

Output

/home/tvt/workspace/favtuts/data/resize-fast.gif
/home/tvt/workspace/favtuts/data/resize-default.png
/home/tvt/workspace/favtuts/google.png
/home/tvt/workspace/favtuts/folder/favtuts-banner.jpg
/home/tvt/workspace/favtuts/folder/java.gif
/home/tvt/workspace/favtuts/folder/logo-new.png
/home/tvt/workspace/favtuts/google.jpg

2.2 The isEndWith() method can be shorter with Java 8 stream anyMatch.

private static boolean isEndWith(String file, String[] fileExtensions) {

    // Java 8, try this
    boolean result = Arrays.stream(fileExtensions).anyMatch(file::endsWith);
    return result;

    // old school style
    /*boolean result = false;
    for (String fileExtension : fileExtensions) {
        if (file.endsWith(fileExtension)) {
            result = true;
            break;
        }
    }
    return result;*/
}

2.3 We also can remove the isEndWith() method and puts the anyMatch into the filter directly.

  public static List<String> findFiles(Path path, String[] fileExtensions)
      throws IOException {

      if (!Files.isDirectory(path)) {
          throw new IllegalArgumentException("Path must be a directory!");
      }

      List<String> result;
      try (Stream<Path> walk = Files.walk(path, 1)) {
          result = walk
                  .filter(p -> !Files.isDirectory(p))
                  // convert path to string
                  .map(p -> p.toString().toLowerCase())
                  //.filter(f -> isEndWith(f, fileExtensions))

                  // lambda
                  //.filter(f -> Arrays.stream(fileExtensions).anyMatch(ext -> f.endsWith(ext)))

                  // method reference
                  .filter(f -> Arrays.stream(fileExtensions).anyMatch(f::endsWith))     
                  .collect(Collectors.toList());
      }
      return result;

  }

2.4 We can further enhance the program by passing different conditions into the stream filter; Now, the program can easily search or find files with a specified pattern from a folder. For examples:

Find files with filename starts with “abc”.

  List<String> result;
  try (Stream<Path> walk = Files.walk(path)) {
      result = walk
              .filter(p -> !Files.isDirectory(p))
              // convert path to string
              .map(p -> p.toString())
              .filter(f -> f.startsWith("abc"))
              .collect(Collectors.toList());
  }

Find files with filename containing the words “favtuts”.

  List<String> result;
  try (Stream<Path> walk = Files.walk(path)) {
      result = walk
              .filter(p -> !Files.isDirectory(p))
              // convert path to string
              .map(p -> p.toString())
              .filter(f -> f.contains("favtuts"))
              .collect(Collectors.toList());
  }

Download Source Code

$ git clone https://github.com/favtuts/java-core-tutorials-examples

$ cd java-io/howto

References

Leave a Reply

Your email address will not be published. Required fields are marked *