Java에서 재귀 적으로 디렉토리 삭제


382

Java에서 전체 디렉토리를 재귀 적으로 삭제하는 방법이 있습니까?

일반적인 경우 빈 디렉토리를 삭제할 수 있습니다. 그러나 내용이있는 전체 디렉토리를 삭제하는 경우 더 이상 간단하지 않습니다.

Java로 내용이 포함 된 전체 디렉토리를 어떻게 삭제합니까?


4
비어 있지 않은 디렉토리로 File.delete ()를 호출하면 단순히 false를 반환해야합니다.
Ben S

Java 8을 사용하는 경우 @RoK의 답변을 참조하십시오.
Robin

답변:


462

Apache의 commons-io를 확인해야합니다 . 그것은 당신이 원하는 것을 할 FileUtils 클래스를 가지고 있습니다.

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

3
이 함수는 아마 erickson이 그의 답변에서 제공 한 코드를 감쌀 것입니다.
paweloque 2009

14
좀 더 철저합니다. Linux / Unix에서 심볼릭 링크와 같은 것을 올바르게 처리합니다. svn.apache.org/viewvc/commons/proper/io/trunk/src/java/org/…
Steve 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을 사용하면 마지막 으로 안정적인 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);
}

11
File.delete ()에는 해당 기능이 없습니다.
Ben S

14
@Erickson : FileNotFoundException이 삭제 실패에 대한 나쁜 예외가 아닙니까? 파일이 더 이상 존재하지 않으면 파일이 이미 삭제되어 있어야합니다. 즉, 의미 적으로 삭제가 실패하지 않았 음을 의미합니다. 그리고 다른 이유로 실패한 경우 파일을 찾을 수 없기 때문이 아닙니다.
Lawrence Dol

46
아주 조심 . 심볼릭 링크를 역 참조합니다. 당신은 예를 들어 리눅스에 있으며, 폴더가있는 경우 foo링크와 foo/link같은 것을 link->/호출, delete(new File(foo)) 사용자가 허용 될 때, 파일 시스템의 많은으로 삭제됩니다 !!
Miquel

4
@Miquel 이해가되지 않습니다-왜 조심하고 싶습니까? 제공된 코드의 요점은 전체 디렉토리를 제거하는 것입니다. 나는 여기에 어떤 위험이 있는지 이해하지 못한다.
Joehot200

12
@ Joehot200 당신이 맞습니다. 디렉토리 symlink에서 delete를 호출하면 디렉토리가 삭제되지 않고 symlink 자체 만 삭제됩니다. 디렉토리를 삭제하려면 실제로 ReadSymbolicLink를 사용하여 symlink를 명시 적으로 따라야 합니다. 내 잘못이야! 잘 발견
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

1
"진주를 바다 깊은 곳으로 다이빙합니다." 이것은 내가 찾은 가장 작은 해결책입니다. 그것을 찾기 위해 깊게 뛰어 들었다. 훌륭한!
Basil Musa

20
"코드는"간단하게 dir을 삭제하는 "매우 단순하지 않다":-) 그러나 이것이 순수한 자바에서 가장 좋은 솔루션이라고 생각합니다.
Mat

1
여기에 사용 된 walkFileTree 과부하는 " 심볼릭 링크 "를 따르지 않습니다 . (Javadoc : docs.oracle.com/javase/7/docs/api/java/nio/file/… )
Stephan

1
도보로 디렉토리를 나열 할 수없는 경우 날려 버릴 수 super.postVisitDirectory(dir, exc);있도록 postVisitDirectory메소드를 호출해야합니다 .
Tom Anderson

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)"의 빼기 부호에주의하십시오. (Comparator.reverseOrder) .sorted으로는 동일합니다
한국

Files.walk는 순차적입니까? 또는 비어 있지 않은 디렉토리를 삭제하지 않으려면이 답변에 forEach 대신 forEachOrdered가 필요합니까?
Silwing 2009 년

그냥 사용 .sorted((f1, f2) -> f2.compareTo(f1)), 비교 f2f1대신 f1f2.
Beto Neto

67

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의 것 입니다. 프로세스는 개인용이지만 그 동작은 분명해야합니다.)


Files.walkFileTree에서 한 가지 문제를 발견했습니다. 옵션이 부족할 때까지 파일을 계속 삭제하는 재귀 삭제 버전을 구현하기에는 충분하지 않습니다. 페일 패스트 버전에는 적합하지만, 페일 패스트가 항상 원하는 것은 아닙니다 (예를 들어 임시 파일을 정리하는 경우, 페일 패스트가 아닌 삭제를 원합니다.)
Trejkaz

왜 그런지 모르겠습니다. 원하는 오류를 처리 할 수 ​​있습니다. 빠르게 실패하지 않아도됩니다. 내가 예상 할 수있는 유일한 문제는 현재 디렉토리를 걷는 동안 생성되는 새 파일을 처리하지 못할 수도 있지만 사용자 정의 솔루션에 더 적합한 고유 한 상황입니다.
Trevor Robinson

1
visitFile에서 오류를 억제하고 실패한 단일 파일에서 walkFileTree를 호출하면 오류가 발생 하지 않습니다 (따라서 visitFile 발생하는 오류를 전파 해야 합니다.) 디렉토리를 삭제하고 하나의 파일을 삭제하지 못하면 유일한 콜백이 호출됩니다. postVisitDirectory입니다. 즉, 한 파일을 방문하는 동안 오류가 발생하면 디렉토리의 다른 파일을 방문하지 않습니다. 이것이 내가 의미하는 바입니다. 아마도이 문제를 해결할 수있는 방법이있을 것이라고 확신하지만이 시점까지는 전통적인 재귀 삭제 루틴보다 더 많은 코드를 이미 작성 했으므로 사용하지 않기로 결정했습니다.
Trejkaz

첫 번째 코드에 감사드립니다. 유용했지만 간단한 델 트리를 완료하지 못했기 때문에 변경해야했습니다. "postVisitDirectory"의 예외를 무시하고 다음과 같은 간단한 트리가 완전히 수행 할 수 없기 때문에 계속을 반환해야했습니다. 삭제 : 내부에 하나의 파일이있는 다른 디렉토리가있는 디렉토리. Windows에서 얻을 수있는 모든 것이 단순 / 정상입니다.
Dreamspace President

그것은 모두 내가 얻은 java.nio.file.DirectoryNotEmptyException에서 시작되었습니다. visitFileFailed가 사용되는 경우를 발견했습니다. 디렉토리 구조에 Windows에 정션 유형 링크가있는 경우 이로 인해 두 가지 문제가 발생할 수 있습니다. *) Files.walkFileTree는 정션으로 연결되는 링크를 따라 가면서 그곳의 모든 것을 삭제합니다. *) 정션 대상 디렉토리가 이미 삭제 된 경우, Files.walkFileTree에 의한 링크 구문 분석이 visitFileFailed에서 발견 된 NoSuchFileException으로 실패합니다.
Andres Luuk

34

방금 내 솔루션이 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();
    }
}

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

4
일반적으로 수백 개의 메소드 호출을 중첩시키는 데 문제가 없다는 것을 알기 때문에 파일 시스템 제한 사항이 훨씬 빠르다고 생각합니다.
Bombe

2
list*class 의 메소드에 주의하십시오 java.io.File. Javadoc에서 : "이 추상 경로 이름이 디렉토리를 나타내지 않거나 I / O 오류가 발생하면 널을 리턴합니다." 그래서 : if (currList.length > 0) {이된다if (null != currList && currList.length > 0) {
kevinarpe

1
약간 빠른 스택 대신 ArrayDeque를 사용합니다. (동기화되지 않음)
Wytze


15

구아바구아바 9Files.deleteRecursively(File) 까지 지원 했다 .

에서 구아바 10 :

더 이상 사용되지 않습니다. 이 방법은 심볼릭 링크 감지 및 경쟁 조건이 열악합니다. 이 기능은 rm -rf또는 과 같은 운영 체제 명령을 셸링하여 만 적절히 지원할 수 있습니다 del /s. 이 방법은 Guava 릴리스 11.0의 Guava에서 제거 될 예정입니다.

따라서 구아바 11 에는 그러한 방법이 없습니다 .


6
너무 나쁘다. 포격은 약간 거칠고 휴대하기 어려운 것 같습니다. Apache commons 버전이 제대로 작동하면 구현이 불가능하지 않을 수 있습니다.
Andrew McKinlay

6
@andrew 아파치 커먼즈 구현은 구아바가 구현을 제거하게하는 것과 비슷한 문제를 가져야합니다. code.google.com/p/guava-libraries/issues/detail?id=365
orip

아파치 커먼즈 버전은 심볼릭 링크를 감지하고 단순히 파일의 자식을 가로 지르지 않습니다.
Ajax

5
Guava 21.0은 이것을 MoreFiles.deleteRecursively () 로 추가했습니다 .
Robert Fleming

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
이렇게하면 스칼라 버전을 만들 수있었습니다.Files.walk(path).iterator().toSeq.reverse.foreach(Files.delete)
James Ward

정렬이 정말로 필요합니까? 이 walk방법은 이미 깊이 우선 순회를 보장합니다.
VGR

Collections.reverseOrder()코드를 for (Path p : Files.walk(directoryToDelete).sorted(reverseOrder()).toArray(Path[]::new))정적으로 가져온 것으로 가정 하여 비교기를 재활용 할 수 있습니다 .
namero999

@ namero999 무슨 뜻 Comparator.reverseOrder인가요? Files.walk(dir) .sorted(Comparator.reverseOrder()) .toArray(Path[]::new))
Jeff

@Jeff 매우 당신이 바로, 주로 메모리에 의해 갔다하는이 :)
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();
    }
}

좋은 코드이지만 수정되면 버그가 하나 있습니다. 라인 f.delete()아래 deleteDirectory(f)때문에 의지 NoSuchFileException을 던져 deleteDirectory(f)이미 해당 파일을 삭제합니다. 에 deleteDirectory(f)의해 전달 되고 삭제 될 때 모든 디렉토리는 경로 가됩니다 path.delete(). 따라서 섹션 f.delete()에서 필요하지 않습니다 if f.isDerectory. 따라서 f.delete();deleteDirectory (f)에서 삭제 하면 작동합니다.
Trieu Nguyen

5

심볼릭 링크와 위의 코드로 실패하는 두 가지 방법은 ... 솔루션을 모릅니다.

방법 # 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 -type 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

이 문제에 대한 해결책은 erickson의 답변 코드를 사용하여 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"과 같은 대부분의 명령 셸 유틸리티의 동작을 모방하기 위해 구현 된 것 같습니다. 두 가지 대안 중 현재 구현은 전체적인 놀라움 (및 분노) 잠재력을 확실히 최소화합니다. 변경되지 않습니다.
erickson

4
일반적으로, 내가 볼 수있는 유일한 Java JRE 패키지는 Swing에서 온 것입니다. 일반적으로 java.io.File과 같은 다른 클래스를 확장하는 것은 예상치 못한 방식으로 작동 할 가능성이 있기 때문에 나쁜 생각입니다.
Eddie

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.deleteDirectory1 분 밖에 걸리지 않습니다 rm -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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.