如何递归删除文件夹而不跟随符号链接?

3

我正在使用Apache Commons' FileUtils.deleteDirectory() 递归删除文件夹,但我注意到它会跟随符号链接。

是否有一种替代方法可以不跟随符号链接,而只删除实际的文件和文件夹?或者,我能否调整FileUtils来实现这一点?


相关问题:https://dev59.com/vHI95IYBdhLWcg3wvgl9 - Lukas Eder
我记得曾经在Java中看到过一个特定于操作系统的IO实现,但是我忘记了在哪里看到的...让我们等待另一个答案。 - Lukas Eder
我认为你不能调整FileUtils来实现你想要的功能。如果你想要自己实现,也许DirectoryWalkerFileUtils.isSymlink(File file)可以加速你的进程。 - Ulrich von Poblotzki
@UlrichvonPoblotzki - 我正在复制粘贴FileUtils.deleteDirectory() - 很快就会发布结果。 - ripper234
https://dev59.com/p17Va4cB1Zd3GeqPMbve - ripper234
显示剩余2条评论
2个回答

2
我简化了 ripper234 的答案。
/**
 * Recursively deletes `item`, which may be a directory.
 * Symbolic links will be deleted instead of their referents.
 * Returns a boolean indicating whether `item` still exists.
 * https://dev59.com/cl7Va4cB1Zd3GeqPMbve
 */
public static boolean deleteRecursiveIfExists(File item) {
    if (!item.exists()) return true;
    if (!Files.isSymbolicLink(item.toPath()) && item.isDirectory()) {
        File[] subitems = item.listFiles();
        for (File subitem : subitems)
            if (!deleteRecursiveIfExists(subitem)) return false;
    }
    return item.delete();
}

1
整个问题似乎源于FileUtils.isSymlink()中的一个明显的错误(我刚刚报告了它)。我复制并粘贴了deleteDirectory()的代码,并使用Java 7的API来检查符号链接,结果它可以正常工作:
public static void deleteDirectory(File directory) throws IOException {
    // See https://dev59.com/cl7Va4cB1Zd3GeqPMbve
    // Copied from http://grepcode.com/file/repo1.maven.org/maven2/commons-io/commons-io/2.1/org/apache/commons/io/FileUtils.java#FileUtils.deleteDirectory%28java.io.File%29
    if (!directory.exists()) {
        return;
    }

    if (!Files.isSymbolicLink(directory.toPath())) {
        cleanDirectory(directory);
    }

    if (!directory.delete()) {
        String message = "Unable to delete directory " + directory + ".";
        throw new IOException(message);
    }
}

private static void cleanDirectory(File directory) throws IOException {
    // Copied from http://grepcode.com/file/repo1.maven.org/maven2/commons-io/commons-io/2.1/org/apache/commons/io/FileUtils.java#FileUtils.cleanDirectory%28java.io.File%29
    if (!directory.exists()) {
        String message = directory + " does not exist";
        throw new IllegalArgumentException(message);
    }

    if (!directory.isDirectory()) {
        String message = directory + " is not a directory";
        throw new IllegalArgumentException(message);
    }

    File[] files = directory.listFiles();
    if (files == null) {  // null if security restricted
        throw new IOException("Failed to list contents of " + directory);
    }

    IOException exception = null;
    for (File file : files) {
        try {
            forceDelete(file);
        } catch (IOException ioe) {
            exception = ioe;
        }
    }

    if (exception != null) {
        throw exception;
    }
}

private static void forceDelete(File file) throws IOException {
    if (file.isDirectory()) {
        deleteDirectory(file);
    } else {
        boolean filePresent = file.exists();
        if (!file.delete()) {
            if (!filePresent) {
                throw new FileNotFoundException("File does not exist: " + file);
            }
            String message =
                    "Unable to delete file: " + file;
            throw new IOException(message);
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接