As a brief note to self, if you ever want to write some code using Scala that recursively descends through a directory tree, here’s a solution that uses the Java SimpleFileVisitor
and Files.walkFileTree
method. First, here’s a skeleton class for the SimpleFileVisitor
part of the solution:
import java.io._
import java.nio.file._
import java.nio.file.attribute._
import java.nio.file.FileVisitResult._
import java.nio.file.FileVisitOption._
import scala.io.Source
class Finder (filePattern: String, searchPattern: String)
extends SimpleFileVisitor[Path] {
var pathMatcher: PathMatcher = null
var numMatches = 0
// note: "glob:" is part of the syntax
// https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String-
pathMatcher = FileSystems.getDefault()
.getPathMatcher("glob:" + filePattern)
// add code here to work on files
override def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult = {
find(file)
return CONTINUE
}
// add code here to work on directories
override def preVisitDirectory(dir: Path, attrs: BasicFileAttributes): FileVisitResult = {
println(s"DIR: ${dir.toAbsolutePath()}")
return CONTINUE
}
override def visitFileFailed(file: Path, ioe: IOException): FileVisitResult = {
System.err.println(ioe)
return CONTINUE
}
// compares the glob filePattern against the file or directory name
def find(file: Path): Unit = {
val name: Path = file.getFileName()
// if the `name` matches what you’re looking for, do
// what you want here with the file
if (name != null && pathMatcher.matches(name)) {
numMatches += 1
val canonFilename = file.toAbsolutePath.toString
println(s"match: $canonFilename")
}
}
def done() = {
println(s"Searched $numMatches $filePattern files.\n")
}
}
In that class, just implement the visitFile
, preVisitDirectory
, and visitFileFailed
methods as desired.
Next, here’s a Scala object that shows how to use that SimpleFileVisitor
import java.nio.file._
object FileFinder extends App {
val finder = new Finder(
"*.scala",
"App"
)
Files.walkFileTree(
Paths.get("/Users/al/Projects/Scala"),
finder
)
finder.done()
}
The combination of that class and object can be read as, “Search the /Users/al/Projects/Scala directory tree for all Scala files that contain the string App
.” Notice how the Finder
— which extends SimpleFileVisitor
— is passed into the walkFileTree
method of the Files
class.
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |
Summary
There’s more that can be said about how this code works, but for today, if you need a Java or Scala solution that lets you search a directory structure for files and directories, I hope this skeleton code is helpful.