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:38

Using java 6 without using dependencies this is pretty much the only way to do so.
The problem with your function is that it return Unit (which I btw would explicit note it using def delete(file: File): Unit = {

I took your code and modify it to return map from file name to the deleting status.

def delete(file: File): Array[(String, Boolean)] = {
  Option(file.listFiles).map(_.flatMap(f => delete(f))).getOrElse(Array()) :+ (file.getPath -> file.delete)
}
查看更多
家丑人穷心不美
3楼-- · 2020-08-09 05:40

Expanding on Vladimir Matveev's NIO2 solution:

object Util {
  import java.io.IOException
  import java.nio.file.{Files, Paths, Path, SimpleFileVisitor, FileVisitResult}
  import java.nio.file.attribute.BasicFileAttributes

  def remove(root: Path, deleteRoot: Boolean = true): Unit =
    Files.walkFileTree(root, new SimpleFileVisitor[Path] {
      override def visitFile(file: Path, attributes: BasicFileAttributes): FileVisitResult = {
        Files.delete(file)
        FileVisitResult.CONTINUE
      }

      override def postVisitDirectory(dir: Path, exception: IOException): FileVisitResult = {
        if (deleteRoot) Files.delete(dir)
        FileVisitResult.CONTINUE
      }
    })

  def removeUnder(string: String): Unit = remove(Paths.get(string), deleteRoot=false)

  def removeAll(string: String): Unit = remove(Paths.get(string))

  def removeUnder(file: java.io.File): Unit = remove(file.toPath, deleteRoot=false)

  def removeAll(file: java.io.File): Unit = remove(file.toPath)
}
查看更多
Summer. ? 凉城
4楼-- · 2020-08-09 05:43

With pure scala + java way

import scala.reflect.io.Directory
import java.io.File

val directory = new Directory(new File("/sampleDirectory"))
directory.deleteRecursively()

deleteRecursively() Returns false on failure

查看更多
叼着烟拽天下
5楼-- · 2020-08-09 05:45

From http://alvinalexander.com/blog/post/java/java-io-faq-how-delete-directory-tree

Using Apache Common IO

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.WildcardFileFilter;
public void deleteDirectory(String directoryName)
throws IOException
{
  try
  {
    FileUtils.deleteDirectory(new File(directoryName));
  }
  catch (IOException ioe)
  {
    // log the exception here
    ioe.printStackTrace();
    throw ioe;
  }
}

The Scala one can just do this...

import org.apache.commons.io.FileUtils
import org.apache.commons.io.filefilter.WildcardFileFilter
FileUtils.deleteDirectory(new File(outputFile))

Maven Repo Imports

查看更多
ゆ 、 Hurt°
6楼-- · 2020-08-09 05:46

Using the Java NIO.2 API:

import java.nio.file.{Files, Paths, Path, SimpleFileVisitor, FileVisitResult}
import java.nio.file.attribute.BasicFileAttributes

def remove(root: Path): Unit = {
  Files.walkFileTree(root, new SimpleFileVisitor[Path] {
    override def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult = {
      Files.delete(file)
      FileVisitResult.CONTINUE
    }
    override def postVisitDirectory(dir: Path, exc: IOException): FileVisitResult = {
      Files.delete(dir)
      FileVisitResult.CONTINUE
    }
  })
}

remove(Paths.get("/tmp/testdir"))

Really, it's a pity that the NIO.2 API is with us for so many years and yet few people are using it, even though it is really superior to the old File API.

查看更多
Animai°情兽
7楼-- · 2020-08-09 05:46

To add to Slavik Muz's answer:

def deleteFile(file: File): Boolean = {

  def childrenOf(file: File): List[File] = Option(file.listFiles()).getOrElse(Array.empty).toList

  @annotation.tailrec
  def loop(files: List[File]): Boolean = files match {

    case Nil ⇒ true

    case child :: parents if child.isDirectory && child.listFiles().nonEmpty ⇒
      loop((childrenOf(child) :+ child) ++ parents)

    case fileOrEmptyDir :: rest ⇒
      println(s"deleting $fileOrEmptyDir")
      fileOrEmptyDir.delete()
      loop(rest)

  }

  if (!file.exists()) false
  else loop(childrenOf(file) :+ file)
}
查看更多
登录 后发表回答