Delete directory recursively in Scala

2020-08-09 04:58发布

I am writing the following (with Scala 2.10 and Java 6):

import java.io._

def delete(file: File) {
  if (file.isDirectory) 
    Option(file.listFiles).map(_.toList).getOrElse(Nil).foreach(delete(_))
  file.delete
}

How would you improve it ? The code seems working but it ignores the return value of java.io.File.delete. Can it be done easier with scala.io instead of java.io ?

标签: java scala file
12条回答
霸刀☆藐视天下
2楼-- · 2020-08-09 05:47

Try this code that throws an exception if it fails:

def deleteRecursively(file: File): Unit = {
  if (file.isDirectory) {
    file.listFiles.foreach(deleteRecursively)
  }
  if (file.exists && !file.delete) {
    throw new Exception(s"Unable to delete ${file.getAbsolutePath}")
  }
}

You could also fold or map over the delete if you want to return a value for all the deletes.

查看更多
贼婆χ
3楼-- · 2020-08-09 05:48

What I ended up with

def deleteRecursively(f: File): Boolean = {
  if (f.isDirectory) f.listFiles match {
    case files: Array[File] => files.foreach(deleteRecursively)
    case null =>
  }
  f.delete()
}
查看更多
干净又极端
4楼-- · 2020-08-09 05:58

Getting little lengthy, but here's one that combines the recursivity of Garrette's solution with the npe-safety of the original question.

def deleteFile(path: String) = {
  val penultimateFile = new File(path.split('/').take(2).mkString("/"))
  def getFiles(f: File): Set[File] = {
    Option(f.listFiles)
      .map(a => a.toSet)
      .getOrElse(Set.empty)
  }
  def getRecursively(f: File): Set[File] = {
    val files = getFiles(f)
    val subDirectories = files.filter(path => path.isDirectory)
    subDirectories.flatMap(getRecursively) ++ files + penultimateFile
  }
  getRecursively(penultimateFile).foreach(file => {
    if (getFiles(file).isEmpty && file.getAbsoluteFile().exists) file.delete
  })
}
查看更多
Animai°情兽
5楼-- · 2020-08-09 06:01

Using scala IO

import scalax.file.Path

val path = Path.fromString("/tmp/testfile")    
try {
  path.deleteRecursively(continueOnFailure = false) 
} catch {
  case e: IOException => // some file could not be deleted
}

or better, you could use a Try

val path: Path = Path ("/tmp/file")
Try(path.deleteRecursively(continueOnFailure = false))

which will either result in a Success[Int] containing the number of files deleted, or a Failure[IOException].

查看更多
何必那么认真
6楼-- · 2020-08-09 06:05

This one uses java.io but one can delete directories matching it with wildcard string which may or may not contain any content within it.

 for (file <- new File("<path as String>").listFiles;
        if( file.getName() matches("[1-9]*"))) FileUtils.deleteDirectory(file)

Directory structure e.g. * A/1/, A/2/, A/300/ ... thats why the regex String: [1-9]*, couldn't find a File API in scala which supports regex(may be i missed something).

查看更多
我命由我不由天
7楼-- · 2020-08-09 06:05

This is recursive method that clean all in directory, and return count of deleted files

def cleanDir(dir: File): Int = {

      @tailrec
      def loop(list: Array[File], deletedFiles: Int): Int = {
        if (list.isEmpty) deletedFiles
        else {
          if (list.head.isDirectory && !list.head.listFiles().isEmpty) {
            loop(list.head.listFiles() ++ list.tail ++ Array(list.head), deletedFiles)
          } else {
            val isDeleted = list.head.delete()
            if (isDeleted) loop(list.tail, deletedFiles + 1)
            else loop(list.tail, deletedFiles)
          }
        }
      }

      loop(dir.listFiles(), 0)
    }
查看更多
登录 后发表回答