How to list files in a directory in Scala (and filter the list)

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 12.9, “How to list files in a directory in Scala (and filtering them).”

Problem

Using Scala, you want to get a list of files that are in a directory, potentially limiting the list of files with a filtering algorithm.

Solution

Scala doesn’t offer any different methods for working with directories, so use the listFiles method of the Java File class. For instance, this method creates a list of all files in a directory:

def getListOfFiles(dir: String):List[File] = {
    val d = new File(dir)
    if (d.exists && d.isDirectory) {
        d.listFiles.filter(_.isFile).toList
    } else {
        List[File]()
    }
}

The REPL demonstrates how you can use this method:

scala> import java.io.File
import java.io.File

scala> val files = getListOfFiles("/tmp")
files: List[java.io.File] = List(/tmp/foo.log, /tmp/Files.scala.swp)

Note that if you’re sure that the file you’re given is a directory and it exists, you can shorten this method to just the following code:

def getListOfFiles(dir: File):List[File] = dir.listFiles.filter(_.isFile).toList

Discussion

Be careful, because per the Java Files class Javadoc, this method can throw a SecurityException if your application does not have read access to the directory. Per this tweet it may also return null. (Many thanks to Twitter user ComFreek!)

If you want to limit the list of files that are returned based on their filename extension, in Java, you’d implement a FileFilter with an accept method to filter the filenames that are returned. In Scala, you can write the equivalent code without requiring a FileFilter. Assuming that the File you’re given represents a directory that is known to exist, the following method shows how to filter a set of files based on the filename extensions that should be returned:

import java.io.File

def getListOfFiles(dir: File, extensions: List[String]): List[File] = {
    dir.listFiles.filter(_.isFile).toList.filter { file =>
        extensions.exists(file.getName.endsWith(_))
    }
}

You can call this method as follows to list all WAV and MP3 files in a given directory:

val okFileExtensions = List("wav", "mp3")
val files = getListOfFiles(new File("/tmp"), okFileExtensions)

As long as this method is given a directory that exists, this method will return an empty List if no matching files are found:

scala> val files = getListOfFiles(new File("/Users/Al"), okFileExtensions)
files: List[java.io.File] = List()

This is nice, because you can use the result normally, without having to worry about a null value:

scala> files.foreach(println)
(no output or errors, because an empty List was returned)

... this post is sponsored by my books ...
 

See Also