Java - 하위 폴더, 파일 모두 삭제하는 방법

JS · 29 Apr 2020

File 클래스를 이용하면 파일을 삭제할 수 있습니다. File.delete()를 이용하면 1개의 파일이나 폴더를 삭제할 수 있지만, 폴더 안에 파일이 들어있는 경우 삭제를 할 수 없습니다.

이런 경우 재귀적으로 파일을 모두 찾아서 삭제를 하도록 구현하거나, 이런 내용이 구현되어있는 자바 라이브러리를 사용하면 됩니다.

모든 하위 폴더, 파일 삭제 (Recursively)

먼저 재귀적으로 하위 파일들을 모두 찾아 삭제하는 코드를 소개합니다.

저는 /home/mjs/test/myfolder 경로에 폴더를 만들었고 그 하위에 폴더와 파일들을 많이 만들었습니다. tree 명령어로 구조를 보면 아래와 같습니다.

/home/mjs/test/myfolder$ tree
.
├── file1.txt
├── folder1
│   └── file2.txt
├── folder2
│   ├── file3.txt
│   └── file4.txt
├── folder3
│   ├── file5.txt
│   ├── file6.txt
│   └── folder4
│       ├── text2.txt
│       ├── text3.txt
│       └── text.txt
└── myscript.sh

아래 코드는 /home/mjs/test/myfolder 폴더를 포함한 모든 하위 파일들을 재귀적(recursive)으로 삭제하는 코드입니다.

public class DeleteFilesRecursively {

    public static void main(String args[]) throws ParseException {
        File rootDir = new File("/home/mjs/test/myfolder");
        deleteFilesRecursively(rootDir);
    }

    static boolean deleteFilesRecursively(File rootFile) {
        File[] allFiles = rootFile.listFiles();
        if (allFiles != null) {
            for (File file : allFiles) {
                deleteFilesRecursively(file);
            }
        }
        System.out.println("Remove file: " + rootFile.getPath());
        return rootFile.delete();

    }
}

File이 폴더라면 listFiles()는 그 하위의 파일들을 리스트로 리턴해줍니다. File이 폴더가 아니라면 null을 리턴합니다.

실행하면 다음과 같은 로그가 출력되면서 모든 파일이 삭제됩니다.

Remove file: /home/mjs/test/myfolder/folder1/file2.txt
Remove file: /home/mjs/test/myfolder/folder1
Remove file: /home/mjs/test/myfolder/file1.txt
Remove file: /home/mjs/test/myfolder/myscript.sh
Remove file: /home/mjs/test/myfolder/folder3/file5.txt
Remove file: /home/mjs/test/myfolder/folder3/folder4/text3.txt
Remove file: /home/mjs/test/myfolder/folder3/folder4/text2.txt
Remove file: /home/mjs/test/myfolder/folder3/folder4/text.txt
Remove file: /home/mjs/test/myfolder/folder3/folder4
Remove file: /home/mjs/test/myfolder/folder3/file6.txt
Remove file: /home/mjs/test/myfolder/folder3
Remove file: /home/mjs/test/myfolder/folder2/file3.txt
Remove file: /home/mjs/test/myfolder/folder2/file4.txt
Remove file: /home/mjs/test/myfolder/folder2
Remove file: /home/mjs/test/myfolder

FileUtils로 하위 폴더, 파일 삭제

위의 예제처럼 직접 구현하는 것이 번거롭고 귀찮다면 commons-io 라이브러리의 FileUtils를 이용할 수 있습니다.

Gradle 프로젝트는 build.gradle의 dependencies에 다음과 같이 추가합니다.

dependencies {
  compile group: 'commons-io', name: 'commons-io', version: '2.6'
  ...
}

Maven 등의 다른 빌드시스템을 사용하는 프로젝트는 mvnrepository.com을 참고하셔서 설정하시면 됩니다.

FileUtils.deleteDirectory()는 인자로 전달되는 파일 및 하위 파일들을 모두 삭제합니다.

아래 코드는 위에서 직접 구현한 코드와 동일한 기능을 수행합니다. 코드를 실행해보면 myfolder의 하위 파일들이 모두 삭제된 것을 확인할 수 있습니다.

try {
    File rootDir = new File("/home/mjs/test/myfolder");
    FileUtils.deleteDirectory(rootDir);
} catch (IOException e) {
    e.printStackTrace();
}

FileUtils 내부에 모든 것이 구현되어있어서 가장 깔끔하고 간편한 방법입니다.

Java8를 이용하여 하위 폴더, 파일 삭제

Java8의 Stream과 Files을 이용하여 파일을 삭제할 수 있습니다.

다음과 같이 모든 파일을 순회하면서 파일을 삭제할 수 있습니다.

try {
    File rootDir = new File("/home/mjs/test/myfolder");
    Files.walk(rootDir.toPath())
            .sorted(Comparator.reverseOrder())
            .map(Path::toFile)
            .forEach((file)->{
                System.out.println("Remove file: " + file.getPath());
                file.delete();
            });
} catch (IOException e) {
    e.printStackTrace();
}

위 코드를 실행하면 다음처럼 로그를 출력하면서 파일을 삭제합니다.

Remove file: /home/mjs/test/myfolder/myscript.sh
Remove file: /home/mjs/test/myfolder/folder3/folder4/text3.txt
Remove file: /home/mjs/test/myfolder/folder3/folder4/text2.txt
Remove file: /home/mjs/test/myfolder/folder3/folder4/text.txt
Remove file: /home/mjs/test/myfolder/folder3/folder4
Remove file: /home/mjs/test/myfolder/folder3/file6.txt
Remove file: /home/mjs/test/myfolder/folder3/file5.txt
Remove file: /home/mjs/test/myfolder/folder3
Remove file: /home/mjs/test/myfolder/folder2/file4.txt
Remove file: /home/mjs/test/myfolder/folder2/file3.txt
Remove file: /home/mjs/test/myfolder/folder2
Remove file: /home/mjs/test/myfolder/folder1/file2.txt
Remove file: /home/mjs/test/myfolder/folder1
Remove file: /home/mjs/test/myfolder/file1.txt
Remove file: /home/mjs/test/myfolder

다음과 같이 forEach에 인자로 전달한 Lambda 대신에 File::delete를 사용할 수도 있습니다.

try {
    File rootDir = new File("/home/mjs/test/myfolder");
    Files.walk(rootDir.toPath())
        .sorted(Comparator.reverseOrder())
        .map(Path::toFile)
        .forEach(File::delete);
} catch (IOException e) {
    e.printStackTrace();
}

특정 파일만 삭제하도록 구현하려면 forEach에서 조건문을 추가하여 특정 파일만 삭제할 수도 있습니다.

참고

댓글을 보거나 쓰려면 이 버튼을 눌러주세요.
codechachaCopyright ©2019 codechacha