Javaでディレクトリを再帰的に削除する


382

Javaでディレクトリ全体を再帰的に削除する方法はありますか?

通常の場合、空のディレクトリを削除することができます。しかし、内容を含むディレクトリ全体を削除することになると、もはやそれほど簡単ではありません。

Javaでコンテンツを含むディレクトリ全体をどのように削除しますか?


4
File.delete()は、空でないディレクトリで呼び出すと、単にfalseを返します。
ベンS

Java 8を使用している場合は、@ RoKの回答を参照してください。
Robin

回答:


462

Apacheのcommons-ioをチェックしてください。それは持っているのfileutilsのあなたがやりたいだろうクラスを。

FileUtils.deleteDirectory(new File("directory"));

3
この関数は、おそらくエリクソンが彼の回答で提供したコードをラップしています。
パウェロク2009

14
それはもう少し詳細です。Linux / Unixではシンボリックリンクなどを正しく処理します。 svn.apache.org/viewvc/commons/proper/io/trunk/src/java/org/...
スティーブ・K


@RichardEB URLは以下のようになります。github.com/apache/commons-io/blob/master/src/main/java/org/...
SWE

Javaにすぐに使える機能があるのに、なぜ別の依存関係を追加するのですか?このページのRoKによって答えを参照、または stackoverflow.com/questions/35988192/...
fooの

190

Java 7を使用すると、信頼できるシンボリックリンク検出を使用して最終的にこれを行うことができます。(Apacheのcommons-io は、で作成されたWindows上のリンクを処理しないため、現時点では信頼できる symlink検出を備えているとは考えていませんmklink。)

歴史のために、ここにシンボリックリンク続く Java 7以前の答えがあります。

void delete(File f) throws IOException {
  if (f.isDirectory()) {
    for (File c : f.listFiles())
      delete(c);
  }
  if (!f.delete())
    throw new FileNotFoundException("Failed to delete file: " + f);
}

11
File.delete()にはその機能はありません。
ベンS

14
@エリクソン:FileNotFoundExceptionは削除の失敗の悪い例外ではありませんか?ファイルが本当に存在しなくなった場合は、既に削除されている必要があります。つまり、意味上、削除は失敗しませんでした。何もする必要がありませんでした。そして、他の理由で失敗した場合、それはファイルが見つからなかったためではありませんでした。
ローレンスドル

46
ことが非常に慎重。これはシンボリックリンクを逆参照します。たとえばLinuxを使用していて、のようなfooリンクがfoo/link含まれているフォルダがあるlink->/場合、を呼び出すdelete(new File(foo)) と、ユーザーが許可されているだけのファイルシステムが削除されます。
Miquel 2013年

4
@Miquel意味がありません-なぜ注意したいのでしょうか?確かに提供されたコードのポイントは、ディレクトリ全体を削除することです。ここで何が危険かわ​​かりません。
Joehot200 2016

12
@ Joehot200正解です。ディレクトリのシンボリックリンクでdeleteを呼び出しても、ディレクトリは削除されず、シンボリックリンクだけが削除されます。ディレクトリを削除するには、実際にはReadSymbolicLinkを使用して明示的にシンボリックリンクをたどる必要があります。悪い!よく見られる
Miquel

148

Java 7以降では、Filesクラスを使用できます。コードは非常に簡単です:

Path directory = Paths.get("/tmp");
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
   @Override
   public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
       Files.delete(file);
       return FileVisitResult.CONTINUE;
   }

   @Override
   public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
       Files.delete(dir);
       return FileVisitResult.CONTINUE;
   }
});

2
このソリューションは非常にエレガントに見え、ディレクトリトラバーサルロジックがまったく含まれていません。
Zero3 2015年

1
「真珠を見つけて海に深く潜る」。これは私が見つけた最も近い解決策です。それを見つけるために深く潜らなければならなかった。鮮やかさ!
バジルムーサ

20
「コードは」単純にディレクトリを削除する「非常に単純」ではありません:-)しかし、それは純粋なJavaでの最良の解決策です。
Mat

1
ここで使用されるwalkFileTreeオーバーロードシンボリックリンクをたどらない」ことに注意してください。(Javadoc:docs.oracle.com/javase/7/docs/api/java/nio/file/…
Stephan

1
ウォークがディレクトリをリストできなかった場合に爆破するためsuper.postVisitDirectory(dir, exc);に、おそらくpostVisitDirectoryメソッドを呼び出す必要があります。
トムアンダーソン

68

開始ディレクトリを含むすべてのファイルとディレクトリを再帰的に削除するワンライナーソリューション(Java8)

Files.walk(Paths.get("c:/dir_to_delete/"))
                .map(Path::toFile)
                .sorted((o1, o2) -> -o1.compareTo(o2))
                .forEach(File::delete);

逆の順序にはコンパレータを使用します。それ以外の場合、File :: deleteは空でない可能性のあるディレクトリを削除できません。したがって、ディレクトリを保持してファイルのみを削除する場合は、sorted()のコンパレータを削除する、並べ替えを完全に削除してファイルフィルターを追加します。

Files.walk(Paths.get("c:/dir_to_delete/"))
                .filter(Files::isRegularFile)
                .map(Path::toFile)
                .forEach(File::delete);

1
すべてのディレクトリを削除するには、最初のソートを.sorted(Comparator :: reverseOrder)に変更する必要があります。それ以外の場合、親ディレクトリは子の前に並べられ、空ではないため削除されません。Java 8を使用している人にとっては素晴らしい答えです!
Robin

1
正しい方法は次.sorted(Comparator.reverseOrder())のとおりです提案Comparator::reverseOrderは機能しませ。参照:stackoverflow.com/questions/43036611/...
user1156544

4
ロビン、「-o1.compareTo(o2)」のマイナス記号に注意してください。.sorted(Comparator.reverseOrder)と同じ
RoK

Files.walkはシーケンシャルですか?または、空ではないディレクトリを削除しようとするのを避けるために、この回答にはforEachではなくforEachOrderedが必要ですか?
5

ただ、使用します.sorted((f1, f2) -> f2.compareTo(f1))、比較f2してf1の代わりf1f2
Beto Neto

67

Java 7は、シンボリックリンク処理でディレクトリを歩くためのサポートを追加しました。

import java.nio.file.*;

public static void removeRecursive(Path path) throws IOException
{
    Files.walkFileTree(path, new SimpleFileVisitor<Path>()
    {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                throws IOException
        {
            Files.delete(file);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException
        {
            // try to delete the file anyway, even if its attributes
            // could not be read, since delete-only access is
            // theoretically possible
            Files.delete(file);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException
        {
            if (exc == null)
            {
                Files.delete(dir);
                return FileVisitResult.CONTINUE;
            }
            else
            {
                // directory iteration failed; propagate exception
                throw exc;
            }
        }
    });
}

これをプラットフォーム固有のメソッドからのフォールバックとして使用します(この テストさいないコード内):

public static void removeDirectory(Path directory) throws IOException
{
    // does nothing if non-existent
    if (Files.exists(directory))
    {
        try
        {
            // prefer OS-dependent directory removal tool
            if (SystemUtils.IS_OS_WINDOWS)
                Processes.execute("%ComSpec%", "/C", "RD /S /Q \"" + directory + '"');
            else if (SystemUtils.IS_OS_UNIX)
                Processes.execute("/bin/rm", "-rf", directory.toString());
        }
        catch (ProcessExecutionException | InterruptedException e)
        {
            // fallback to internal implementation on error
        }

        if (Files.exists(directory))
            removeRecursive(directory);
    }
}

(SystemUtilsはApache Commons Langからのものです。プロセスはプライベートですが、その動作は明らかです。)


Files.walkFileTreeに問題が1つあります。オプションがなくなるまでファイルを削除し続けるバージョンの再帰的削除を実装するには不十分です。これはフェイルファストバージョンには適切ですが、フェイルファストが常に必要なわけではありません(たとえば、一時ファイルをクリーンアップする場合は、フェイルファストではなく、すぐに削除する必要があります。)
Trejkaz

それが本当の理由はわかりません。必要に応じてエラーを処理できます。すぐに失敗する必要はありません。私が予測できる唯一の問題は、現在のディレクトリのウォーク中に作成される新しいファイルを処理しない可能性があることですが、これはカスタムソリューションに適した固有の状況です。
Trevor Robinson

1
visitFileからのエラーを抑制し、失敗した単一のファイルでwalkFileTreeを呼び出すと、エラーは発生しません(したがって、visitFile 発生したエラーを伝播する必要があります)。ディレクトリを削除していて1つのファイルの削除に失敗した場合、唯一のコールバックが呼び出されますpostVisitDirectoryです。つまり、1つのファイルへのアクセス中にエラーが発生した場合、ディレクトリ内の他のファイルにはアクセスしません。これが私の言いたいことです。おそらくこれを回避する方法はあると思いますが、この時点ですでに従来の再帰的削除ルーチンよりも多くのコードを記述していたため、使用しないことにしました。
トレイカズ2013年

最初のコードをありがとう、それは私にとって便利でしたが、単純なdeltreeを完了しなかったため、変更する必要がありました:次の単純なツリーが完全にできなかったため、「postVisitDirectory」の例外を無視してCONTINUEを返す必要がありました削除される:1つのファイルである別のディレクトリが内部にあるディレクトリ。Windowsでは、これらはすべて、シンプルでありふれたものです。
Dreamspace社長

それはすべて、私が受け取ったjava.nio.file.DirectoryNotEmptyExceptionから始まりました。visitFileFailedを使用しているケースを発見しました。Windowsでディレクトリ構造にジャンクションタイプのリンクがある場合。これにより、2つの問題が発生する可能性があります。*)Files.walkFileTreeは、ジャンクションへのリンクをたどり、そこにあるすべてのものを削除します。*)ジャンクションターゲットディレクトリがすでに削除されている場合、Files.walkFileTreeによるリンクの解析は、visitFileFailedでキャッチされるNoSuchFileExceptionで失敗します。
Andres Luuk、2018年

34

私のソリューションがエリクソンのものとほぼ同じで、静的メソッドとしてパッケージ化されているのを見ただけです。これをどこかにドロップします。(ご覧のように)非常に単純なものにすべてのApache Commonsをインストールするよりもはるかに軽量です。

public class FileUtils {
    /**
     * By default File#delete fails for non-empty directories, it works like "rm". 
     * We need something a little more brutual - this does the equivalent of "rm -r"
     * @param path Root File Path
     * @return true iff the file and all sub files/directories have been removed
     * @throws FileNotFoundException
     */
    public static boolean deleteRecursive(File path) throws FileNotFoundException{
        if (!path.exists()) throw new FileNotFoundException(path.getAbsolutePath());
        boolean ret = true;
        if (path.isDirectory()){
            for (File f : path.listFiles()){
                ret = ret && deleteRecursive(f);
            }
        }
        return ret && path.delete();
    }
}

20

スタックあり、再帰メソッドなしのソリューション:

File dir = new File("/path/to/dir");
File[] currList;
Stack<File> stack = new Stack<File>();
stack.push(dir);
while (! stack.isEmpty()) {
    if (stack.lastElement().isDirectory()) {
        currList = stack.lastElement().listFiles();
        if (currList.length > 0) {
            for (File curr: currList) {
                stack.push(curr);
            }
        } else {
            stack.pop().delete();
        }
    } else {
        stack.pop().delete();
    }
}

2
スタックを使用するための+1。これは、ネストされたサブディレクトリの深いレベルを含むディレクトリで機能しますが、他のスタックベースのアプローチは失敗します。
Nathan Osman 2013年

4
通常、数百のメソッド呼び出しをネストすることに問題がないことを確認すると、ファイルシステムの制限にかなり早く遭遇する可能性が高いと思います。
ボンベ2013

2
list*クラスのメソッドに注意してくださいjava.io.File。Javadocsから:「この抽象パス名がディレクトリを示さない場合、またはI / Oエラーが発生した場合は、nullを返します。」したがって、次のようにif (currList.length > 0) {なりますif (null != currList && currList.length > 0) {
kevinarpe 2013

1
少し速いStackの代わりにArrayDequeを使用しています。(非同期)
Wytze 2015年


15

グアバグアバ9Files.deleteRecursively(File)までサポートしていました。

グアバ10から:

非推奨。この方法では、シンボリックリンクの検出と競合状態が悪化します。この機能は、rm -rfまたはなどのオペレーティングシステムコマンドにシェルアウトすることによってのみ適切にサポートできますdel /sこのメソッドは、Guavaリリース11.0でGuavaから削除される予定です。

したがって、グアバ11にはそのような方法はありません。


6
残念な。砲撃は少し粗雑で移植性がないようです。Apacheコモンズバージョンが適切に機能する場合、おそらく実装することは不可能ではありません。
Andrew McKinlay、2011

6
@andrew Apache Commonsの実装には、Guavaによる実装の削除を引き起こす問題と同様の問題があるはずです。code.google.com
p /

Apache Commonsバージョンはシンボリックリンクを検出し、単にファイルの子をトラバースしません。
Ajax

5
Guava 21.0はこれをMoreFiles.deleteRecursively()として追加しました。
ロバートフレミング

12
for(Path p : Files.walk(directoryToDelete).
        sorted((a, b) -> b.compareTo(a)). // reverse; files before dirs
        toArray(Path[]::new))
{
    Files.delete(p);
}

または、あなたが処理したい場合IOException

Files.walk(directoryToDelete).
    sorted((a, b) -> b.compareTo(a)). // reverse; files before dirs
    forEach(p -> {
        try { Files.delete(p); }
        catch(IOException e) { /* ... */ }
      });

2
これは私がScalaのバージョンを考え出す助け:Files.walk(path).iterator().toSeq.reverse.foreach(Files.delete)
ジェームズ・ウォード

並べ替えは本当に必要ですか?このwalk方法では、深度優先のトラバーサルがすでに保証されています。
VGR

コンパレータはからリサイクルできるCollections.reverseOrder()ので、コードはfor (Path p : Files.walk(directoryToDelete).sorted(reverseOrder()).toArray(Path[]::new))静的にインポートされていると想定します 。
namero999 2016年

@ namero999ということComparator.reverseOrderですか?Files.walk(dir) .sorted(Comparator.reverseOrder()) .toArray(Path[]::new))
ジェフ

@ジェフ、あなたが正しいと確信している。主にそこに記憶されていた:)
namero999

11
public void deleteRecursive(File path){
    File[] c = path.listFiles();
    System.out.println("Cleaning out folder:" + path.toString());
    for (File file : c){
        if (file.isDirectory()){
            System.out.println("Deleting file:" + file.toString());
            deleteRecursive(file);
            file.delete();
        } else {
            file.delete();
        }
    }
    path.delete();
}

5
ブール値の戻り値と重複のない拡張バージョン:pastebin.com/PqJyzQUx
Erik Kaplun

9
static public void deleteDirectory(File path) 
{
    if (path == null)
        return;
    if (path.exists())
    {
        for(File f : path.listFiles())
        {
            if(f.isDirectory()) 
            {
                deleteDirectory(f);
                f.delete();
            }
            else
            {
                f.delete();
            }
        }
        path.delete();
    }
}

素晴らしいコードですが、バグが1つあり、修正すると機能します。f.delete()下の行deleteDirectory(f)は、deleteDirectory(f)すでにそのファイルを削除しているため、NoSuchFileExceptionをスローします。すべてのディレクトリは、渡さdeleteDirectory(f)れてによって削除されるときにパスになりpath.delete()ます。したがって、我々は必要としないf.delete()if f.isDerectoryセクション。したがって、f.delete();deleteDirectory(f)の下で削除するだけで機能します。
Trieu Nguyen

5

シンボリックリンクと上記のコードで失敗する2つの方法...そして解決策がわかりません。

方法#1

これを実行してテストを作成します。

echo test > testfile
mkdir dirtodelete
ln -s badlink dirtodelete/badlinktodelete

ここに、テストファイルとテストディレクトリが表示されます。

$ ls testfile dirtodelete
testfile

dirtodelete:
linktodelete

次に、commons-io deleteDirectory()を実行します。ファイルが見つからないと言ってクラッシュします。他の例がここで何をするかわかりません。Linuxのrmコマンドはリンクを削除するだけで、ディレクトリのrm -rも削除します。

Exception in thread "main" java.io.FileNotFoundException: File does not exist: /tmp/dirtodelete/linktodelete

方法#2

これを実行してテストを作成します。

mkdir testdir
echo test > testdir/testfile
mkdir dirtodelete
ln -s ../testdir dirtodelete/dirlinktodelete

ここに、テストファイルとテストディレクトリが表示されます。

$ ls dirtodelete testdir
dirtodelete:
dirlinktodelete

testdir:
testfile

次に、commons-io deleteDirectory()またはユーザーが投稿したサンプルコードを実行します。ディレクトリだけでなく、削除するディレクトリの外にあるテストファイルも削除します。(ディレクトリを暗黙的に逆参照し、コンテンツを削除します)。rm -rはリンクのみを削除します。逆参照されたファイルを削除するには、「find -L dirtodelete -t​​ype f -exec rm {} \;」のようなものを使用する必要があります。

$ ls dirtodelete testdir
ls: cannot access dirtodelete: No such file or directory
testdir:

4

あなたは使うことができます:

org.apache.commons.io.FileUtils.deleteQuietly(destFile);

ファイルを削除し、例外をスローしません。ファイルがディレクトリの場合は、それとすべてのサブディレクトリを削除します。File.delete()とこのメソッドの違いは次のとおりです。削除するディレクトリは空である必要はありません。ファイルまたはディレクトリを削除できない場合、例外はスローされません。


4

メソッドからスローされた例外が一貫して例外を処理する最適なソリューションは、そのメソッドが実行しようとしていた(および失敗した)ことを常に記述する必要があります。

private void deleteRecursive(File f) throws Exception {
    try {
        if (f.isDirectory()) {
            for (File c : f.listFiles()) {
                deleteRecursive(c);
            }
        }
        if (!f.delete()) {
            throw new Exception("Delete command returned false for file: " + f);
        }
    } 
    catch (Exception e) {
        throw new Exception("Failed to delete the folder: " + f, e);
    }
}

3

レガシープロジェクトでは、ネイティブJavaコードを作成する必要があります。Paulitexコードに似たこのコードを作成します。それを見てください:

public class FileHelper {

   public static boolean delete(File fileOrFolder) {
      boolean result = true;
      if(fileOrFolder.isDirectory()) {
         for (File file : fileOrFolder.listFiles()) {
            result = result && delete(file);
         }
      }
      result = result && fileOrFolder.delete();
      return result;
   } 
}

そして単体テスト:

public class FileHelperTest {

    @Before
    public void setup() throws IOException {
       new File("FOLDER_TO_DELETE/SUBFOLDER").mkdirs();
       new File("FOLDER_TO_DELETE/SUBFOLDER_TWO").mkdirs();
       new File("FOLDER_TO_DELETE/SUBFOLDER_TWO/TEST_FILE.txt").createNewFile();
    }

    @Test
    public void deleteFolderWithFiles() {
       File folderToDelete = new File("FOLDER_TO_DELETE");
       Assert.assertTrue(FileHelper.delete(folderToDelete));
       Assert.assertFalse(new File("FOLDER_TO_DELETE").exists());
    }

}

3

以下のコードは、指定されたフォルダー内のすべてのコンテンツを再帰的に削除します。

boolean deleteDirectory(File directoryToBeDeleted) {
    File[] allContents = directoryToBeDeleted.listFiles();
    if (allContents != null) {
        for (File file : allContents) {
            deleteDirectory(file);
        }
    }
    return directoryToBeDeleted.delete();
}

2

以下は、コマンドライン引数を受け入れる基本的なメインメソッドです。必要に応じて、独自のエラーチェックを追加するか、適切な方法で成形する必要があります。

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

public class DeleteFiles {

/**
 * @param intitial arguments take in a source to read from and a 
 * destination to read to
 */
    public static void main(String[] args)
                     throws FileNotFoundException,IOException {
        File src = new File(args[0]);
        if (!src.exists() ) {
            System.out.println("FAILURE!");
        }else{
            // Gathers files in directory
            File[] a = src.listFiles();
            for (int i = 0; i < a.length; i++) {
                //Sends files to recursive deletion method
                fileDelete(a[i]);
            }
            // Deletes original source folder
            src.delete();
            System.out.println("Success!");
        }
    }

    /**
     * @param srcFile Source file to examine
     * @throws FileNotFoundException if File not found
     * @throws IOException if File not found
     */
    private static void fileDelete(File srcFile)
                     throws FileNotFoundException, IOException {
        // Checks if file is a directory
        if (srcFile.isDirectory()) {
            //Gathers files in directory
            File[] b = srcFile.listFiles();
            for (int i = 0; i < b.length; i++) {
                //Recursively deletes all files and sub-directories
                fileDelete(b[i]);
            }
            // Deletes original sub-directory file
            srcFile.delete();
        } else {
            srcFile.delete();
        }
    }
}

お役に立てば幸いです。


1

おそらくこの問題の解決策は、エリクソンの答えからのコードを使用して、Fileクラスのdeleteメソッドを再実装することかもしれません。

public class MyFile extends File {

  ... <- copy constructor

  public boolean delete() {
    if (f.isDirectory()) {
      for (File c : f.listFiles()) {
        return new MyFile(c).delete();
      }
    } else {
        return f.delete();
    }
  }
}

1
「rm」、「rmdir」、「del」などのほとんどのコマンドシェルユーティリティの動作を模倣するために実装されていると思います。2つの選択肢のうち、現在の実装は、全体的な驚き(および怒り)の可能性を確実に最小限に抑えます。変更されることはありません。
エリクソン2009

4
一般的に、私が拡張していると思われるJava JREパッケージは、Swingのものだけです。通常、java.io.Fileなどの他のクラスを拡張することは、予期しない方法で動作する可能性があるため、お勧めできません。
エディ

1

Commons IOおよび<Java SE 7なし

public static void deleteRecursive(File path){
            path.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    if (pathname.isDirectory()) {
                        pathname.listFiles(this);
                        pathname.delete();
                    } else {
                        pathname.delete();
                    }
                    return false;
                }
            });
            path.delete();
        }

0

ファイルはfile.delete()を使用して簡単に削除できますが、削除するにはディレクトリを空にする必要があります。これを簡単に行うには、再帰を使用します。例えば:

public static void clearFolders(String[] args) {
        for(String st : args){
            File folder = new File(st);
            if (folder.isDirectory()) {
                File[] files = folder.listFiles();
                if(files!=null) { 
                    for(File f: files) {
                        if (f.isDirectory()){
                            clearFolders(new String[]{f.getAbsolutePath()});
                            f.delete();
                        } else {
                            f.delete();
                        }
                    }
                }
            }
        }
    }

0

安全に使用するための3つの安全基準を持つこのルーチンをコーディングしました。

package ch.ethz.idsc.queuey.util;

import java.io.File;
import java.io.IOException;

/** recursive file/directory deletion
 * 
 * safety from erroneous use is enhanced by three criteria
 * 1) checking the depth of the directory tree T to be deleted
 * against a permitted upper bound "max_depth"
 * 2) checking the number of files to be deleted #F
 * against a permitted upper bound "max_count"
 * 3) if deletion of a file or directory fails, the process aborts */
public final class FileDelete {
    /** Example: The command
     * FileDelete.of(new File("/user/name/myapp/recordings/log20171024"), 2, 1000);
     * deletes given directory with sub directories of depth of at most 2,
     * and max number of total files less than 1000. No files are deleted
     * if directory tree exceeds 2, or total of files exceed 1000.
     * 
     * abort criteria are described at top of class
     * 
     * @param file
     * @param max_depth
     * @param max_count
     * @return
     * @throws Exception if criteria are not met */
    public static FileDelete of(File file, int max_depth, int max_count) throws IOException {
        return new FileDelete(file, max_depth, max_count);
    }

    // ---
    private final File root;
    private final int max_depth;
    private int removed = 0;

    /** @param root file or a directory. If root is a file, the file will be deleted.
     *            If root is a directory, the directory tree will be deleted.
     * @param max_depth of directory visitor
     * @param max_count of files to delete
     * @throws IOException */
    private FileDelete(final File root, final int max_depth, final int max_count) throws IOException {
        this.root = root;
        this.max_depth = max_depth;
        // ---
        final int count = visitRecursively(root, 0, false);
        if (count <= max_count) // abort criteria 2)
            visitRecursively(root, 0, true);
        else
            throw new IOException("more files to be deleted than allowed (" + max_count + "<=" + count + ") in " + root);
    }

    private int visitRecursively(final File file, final int depth, final boolean delete) throws IOException {
        if (max_depth < depth) // enforce depth limit, abort criteria 1)
            throw new IOException("directory tree exceeds permitted depth");
        // ---
        int count = 0;
        if (file.isDirectory()) // if file is a directory, recur
            for (File entry : file.listFiles())
                count += visitRecursively(entry, depth + 1, delete);
        ++count; // count file as visited
        if (delete) {
            final boolean deleted = file.delete();
            if (!deleted) // abort criteria 3)
                throw new IOException("cannot delete " + file.getAbsolutePath());
            ++removed;
        }
        return count;
    }

    public int deletedCount() {
        return removed;
    }

    public void printNotification() {
        int count = deletedCount();
        if (0 < count)
            System.out.println("deleted " + count + " file(s) in " + root);
    }
}

0

さて、例を考えてみましょう、

import java.io.File;
import java.io.IOException;

public class DeleteDirectory
{
   private static final String folder = "D:/project/java";

   public static void main(String[] args) throws IOException
   {
      File fl = new File(folder);
      if(!fl.exists()) // checking if directory exists
      {
         System.out.println("Sorry!! directory doesn't exist.");
      }
      else
      {
         DeleteDirectory dd = new DeleteDirectory();
         dd.deleteDirectory(fl);
      }
   }

   public void deleteDirectory(File file) throws IOException
   {
      if(file.isDirectory())
      {
         if(file.list().length == 0)
         { 
            deleteEmptyDirectory(file); // here if directory is empty delete we are deleting
         }
         else
         {
            File fe[] = file.listFiles();
            for(File deleteFile : fe)
            {
               deleteDirectory(deleteFile); // recursive call
            }
            if(file.list().length == 0)
            {
               deleteEmptyDirectory(file);
            }
         }
      }
      else
      {
         file.delete();
         System.out.println("File deleted : " + file.getAbsolutePath());
      }
   }

   private void deleteEmptyDirectory(File fi)
   {
      fi.delete();
      System.out.println("Directory deleted : " + fi.getAbsolutePath());
   }
}

詳細については、以下のリソースを参照してください

ディレクトリを削除


0

rm -rfだったずっとよりもパフォーマンスFileUtils.deleteDirectory

広範なベンチマークを行った後、使用rm -rfする方がFileUtils.deleteDirectoryた。

もちろん、小さなディレクトリや単純なディレクトリがある場合は問題になりませんが、私たちの場合、数ギガバイトと深くネストされたサブディレクトリがあり、10分以上かかりFileUtils.deleteDirectoryrm -rf

これを行うための大まかなJava実装を以下に示します。

// Delete directory given and all subdirectories and files (i.e. recursively).
//
static public boolean deleteDirectory( File file ) throws IOException, InterruptedException {

    if ( file.exists() ) {

        String deleteCommand = "rm -rf " + file.getAbsolutePath();
        Runtime runtime = Runtime.getRuntime();

        Process process = runtime.exec( deleteCommand );
        process.waitFor();

        return true;
    }

    return false;

}

大規模なディレクトリや複雑なディレクトリを扱う場合は、試す価値があります。


これはクロスプラットフォームで動作しますか?
OneCricketeer

@ cricket_007どのプラットフォームですか?
Joshua Pinter

ウィンドウズ?OpenWrt?BSD?
OneCricketeer

1
@ cricket_007間違いなくWindowsではありません。これは、AndroidおよびmacOSでテストおよび使用されました。
Joshua Pinter

0

グアバはワンライナーを提供します:MoreFiles.deleteRecursively()

共有される多くの例とは異なり、シンボリックリンクを考慮し、(デフォルトでは)提供されたパスの外のファイルを削除しません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.