Delete all empty folders in Java
Asked Answered
P

6

7

I'd like to write a function that deletes all empty folders, with the option to ignore certain file types (allowed file types are stored in the hashmap) and tell if it should look inside directories.

Calling:

HashMap<String, Boolean> allowedFileTypes = new HashMap<String, Boolean>();
allowedFileTypes.put("pdf", true);
deleteEmptyFolders("ABSOLUTE PATH", allowedFileTypes, true);

Function:

public static void deleteEmptyFolders(String folderPath, HashMap<String, Boolean> allowedFileTypes, boolean followDirectory) {

    File targetFolder = new File(folderPath);
    File[] allFiles = targetFolder.listFiles();


    if (allFiles.length == 0)
        targetFolder.delete();

    else {
        boolean importantFiles = false;

        for (File file : allFiles) {

            String fileType = "folder";
            if (!file.isDirectory())
                fileType = file.getName().substring(file.getName().lastIndexOf('.') + 1);

            if (!importantFiles)
                importantFiles = (allowedFileTypes.get(fileType) != null);

            if (file.isDirectory() && followDirectory)
                deleteEmptyFolders(file.getAbsolutePath(), allowedFileTypes, followDirectory);
        }

        // if there are no important files in the target folder
        if (!importantFiles)
            targetFolder.delete();
    }
}

The problem is that nothing is happening, even though it looks through all folders till the end. Is this a good approach or am I missing something completely?

Precondition answered 24/9, 2014 at 12:57 Comment(5)
Any reason you're using a HashMap instead of a HashSet?Lupien
@Lupien Now that you mention it. No.. I will make it a set, because I will only check if it nulls. Thanks.Precondition
Maybe this can help you a bit: https://mcmap.net/q/149734/-how-to-delete-a-folder-with-files-using-javaSolent
@Mikrobus You are right that was it. You have to delete all files before you can delete a folder. Also sometimes there are hidden config files in the folders, that can be tricky. Thanks you could post it as an answer.Precondition
@Lupien Thanks for your support. I already solved the problem.Precondition
C
7

This piece of code recursively delete all the empty folders or directory:

public class DeleteEmptyDir {
private static final String FOLDER_LOCATION = "E:\\TEST";
private static boolean isFinished = false;

public static void main(String[] args) {

    do {
        isFinished = true;
        replaceText(FOLDER_LOCATION);
    } while (!isFinished);
}

private static void replaceText(String fileLocation) {
    File folder = new File(fileLocation);
    File[] listofFiles = folder.listFiles();
    if (listofFiles.length == 0) {
        System.out.println("Folder Name :: " + folder.getAbsolutePath() + " is deleted.");
        folder.delete();
        isFinished = false;
    } else {
        for (int j = 0; j < listofFiles.length; j++) {
            File file = listofFiles[j];
            if (file.isDirectory()) {
                replaceText(file.getAbsolutePath());
            }
        }
    }
}
}
Cursorial answered 18/1, 2017 at 7:15 Comment(2)
This program never ends if there does not exists a folder that is empty.Masochism
replaceText??? whatOocyte
A
2

Shortest code I could come up with is following Java >=8 code:

        Files.walk(Paths.get("/my/base/dir/"))
                .sorted(Comparator.reverseOrder())
                .map(Path::toFile)
                .filter(File::isDirectory)
                .forEach(File::delete);

Add a second (or more) filter statement with whatever clause you need to include/exclude certain folders. File::delete should not delete folders with contents. Use at own risk.

Affrica answered 25/1, 2021 at 14:41 Comment(1)
This does not delete empty folders recursively.Masochism
D
1

You can use code to delete empty folders using Java.

public static long deleteFolder(String dir) {

        File f = new File(dir);
        String listFiles[] = f.list();
        long totalSize = 0;
        for (String file : listFiles) {

            File folder = new File(dir + "/" + file);
            if (folder.isDirectory()) {
                totalSize += deleteFolder(folder.getAbsolutePath());
            } else {
                totalSize += folder.length();
            }
        }

        if (totalSize ==0) {
            f.delete();
        }

        return totalSize;
    }
Donar answered 9/11, 2017 at 6:5 Comment(1)
file is undifinedMasochism
A
0

Kotlin:

fun deleteAllEmptyDirectories(rootPath: Path): Collection<Path> =
    mutableListOf<Path>()
        .apply {
            Files.walk(testPath)
                .sorted { p1, p2 -> p2.count() - p1.count() }
                .map { it.toFile() }
                .filter { it.isDirectory }
                .forEach {
                    if (it.listFiles().all { el -> el.isDirectory && contains(el.toPath()) }) {
                        val path = it.toPath()
                        add(path)
                        Files.delete(path)
                    }
                }
        }

Test:

 private val testPath = Path.of("build", javaClass.simpleName, UUID.randomUUID().toString())

@Test
fun test() {
    Files.createDirectory(testPath)

    val dirWithTwoEmptySubdirs = Files.createDirectory(testPath.resolve("dirWithTwoEmptySubdirs"))
    val dir1 = Files.createDirectory(dirWithTwoEmptySubdirs.resolve("dir1"))
    val dir2 = Files.createDirectory(dirWithTwoEmptySubdirs.resolve("dir2"))
    val dirWithOneDiffDir = Files.createDirectory(testPath.resolve("dirWithOneDiffDir"))
    var emptyDir = Files.createDirectory(dirWithOneDiffDir.resolve("empty"))
    val notEmptyDir = Files.createDirectory(dirWithOneDiffDir.resolve("notempty"))
    Files.writeString(notEmptyDir.resolve("file.txt"), "asdf")

    assertEquals(
        setOf<Path>(dirWithTwoEmptySubdirs, dir1, dir2, emptyDir),
        deleteAllEmptyDirectories(testPath).toSet()
    )
}
Aurochs answered 23/12, 2021 at 13:41 Comment(0)
M
0

After reading all answers and concluding that all of them have at least one problem I still had to write it myself:

import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Temp {

  public static void main(String[] args) {
    final String path = "D:\\";
    deleteEmpty(new File(path));
  }

  private static int deleteEmpty(File file) {
    List<File> toBeDeleted = Arrays.stream(file.listFiles()).sorted() //
        .filter(File::isDirectory) //
        // Recursive call to delete sub-directories. 
        // If all files in the sub-directory where deleted, also delete this directory. 
        .filter(f -> f.listFiles().length == deleteEmpty(f)) //
        .collect(Collectors.toList());
    int size = toBeDeleted.size();
    toBeDeleted.forEach(t -> {
      final String path = t.getAbsolutePath();
      final boolean delete = t.delete();
      System.out.println("Deleting: \t" + delete + "\t" + path);
    });
    return size;
  }

}
Masochism answered 28/6, 2022 at 11:18 Comment(2)
OP does recursive file deletion, so you'll have to call deleteEmpty for each file you find. Also, don't hesitate to comment on any problems you see in other's answers. It increases the general quality of answers! ;)Threlkeld
This does delete all subfolders, I added some comments to explain the code a bit more.Masochism
M
0
Files.walk(Paths.get("C:\\Temp\\samplefolder")) // works recursively
.map(Path::toFile) // use Java File object
.filter(File::isDirectory) // only consider directories
.filter(f -> f.length() == 0) // make sure no files or directories are in it
.filter(f -> FileUtils.sizeOfDirectory(f) == 0) // use Apache FileUtils here
.forEach(File::delete); // go and delete

This code should work also without Apache Fileutils.sizeOfDirectory() as it counts files and sub-directories inside a directory already.

Maxim answered 26/1 at 14:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.