Java에서 전체 디렉토리를 재귀 적으로 삭제하는 방법이 있습니까?
일반적인 경우 빈 디렉토리를 삭제할 수 있습니다. 그러나 내용이있는 전체 디렉토리를 삭제하는 경우 더 이상 간단하지 않습니다.
Java로 내용이 포함 된 전체 디렉토리를 어떻게 삭제합니까?
답변
Apache의 commons-io를 확인해야합니다 . 그것은 당신이 원하는 것을 할 FileUtils 클래스를 가지고 있습니다.
FileUtils.deleteDirectory(new File("directory"));
답변
Java 7을 사용하면 마지막 으로 안정적인 symlink 탐지를 통해이를 수행 할 수 있습니다 . (아파치의 commons-io는 현재 신뢰할 수있는 symlink 감지 기능 을 가지고 있다고 생각하지 않습니다.mklink
.)
역사를 위해 자바 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);
}
답변
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;
}
});
답변
시작 디렉토리를 포함하여 모든 파일과 디렉토리를 재귀 적으로 삭제하는 단일 라이너 솔루션 (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);
답변
Java 7은 symlink 처리를 사용하여 디렉토리를 걷는 것에 대한 지원을 추가했습니다.
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의 것 입니다. 프로세스는 개인용이지만 그 동작은 분명해야합니다.)
답변
방금 내 솔루션이 erickson과 거의 동일하고 정적 방법으로 패키지 된 것을 보았습니다. 이것을 어딘가에 떨어 뜨리면 (아시다시피) 아주 간단한 것을 위해 모든 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();
}
}
답변
스택이 있고 재귀 적 방법이없는 솔루션 :
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();
}
}
![](http://daplus.net/wp-content/uploads/2023/04/coupang_part-e1630022808943-2.png)