File.delete()
를 이용하면 1개의 파일이나 폴더를 삭제할 수 있지만, 디렉토리(폴더)의 하위 경로에 있는 파일들은 삭제를 할 수 없습니다.
이런 경우 하위의 모든 파일들을 찾아서 삭제를 하도록 구현하거나, 이런 내용이 구현되어있는 자바 라이브러리를 사용하여 삭제해야 합니다.
1. 모든 하위 폴더, 파일 삭제 (Recursively)
먼저 재귀적으로 하위 파일들을 모두 찾아 삭제하는 코드를 소개합니다.
저는 /home/js/test/myfolder
경로에 폴더를 만들었고 그 하위에 폴더와 파일들을 많이 만들었습니다.
tree 명령어로 구조를 보면 아래와 같습니다.
/home/js/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/js/test/myfolder
폴더를 포함한 모든 하위 파일들을 재귀적(recursive)으로 삭제하는 코드입니다.
import java.io.File;
import java.text.ParseException;
public class Example {
public static void main(String args[]) throws ParseException {
File rootDir = new File("/home/js/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/js/test/myfolder/folder1/file2.txt
Remove file: /home/js/test/myfolder/folder1
Remove file: /home/js/test/myfolder/file1.txt
Remove file: /home/js/test/myfolder/myscript.sh
Remove file: /home/js/test/myfolder/folder3/file5.txt
Remove file: /home/js/test/myfolder/folder3/folder4/text3.txt
Remove file: /home/js/test/myfolder/folder3/folder4/text2.txt
Remove file: /home/js/test/myfolder/folder3/folder4/text.txt
Remove file: /home/js/test/myfolder/folder3/folder4
Remove file: /home/js/test/myfolder/folder3/file6.txt
Remove file: /home/js/test/myfolder/folder3
Remove file: /home/js/test/myfolder/folder2/file3.txt
Remove file: /home/js/test/myfolder/folder2/file4.txt
Remove file: /home/js/test/myfolder/folder2
Remove file: /home/js/test/myfolder
2. 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의 하위 파일들이 모두 삭제된 것을 확인할 수 있습니다.
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
public class Example {
public static void main(String args[]) {
try {
File rootDir = new File("/home/js/test/myfolder");
FileUtils.deleteDirectory(rootDir);
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileUtils 내부에 모든 것이 구현되어있어서 가장 깔끔하고 간편한 방법입니다.
3. Files.walk()으로 하위 폴더, 파일 삭제
Java8의 Stream과 Files.walk()을 이용하여 파일을 삭제할 수 있습니다.
다음과 같이 모든 파일을 순회하면서 파일을 삭제할 수 있습니다.
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
public class Example {
public static void main(String args[]) {
try {
File rootDir = new File("/home/js/test/myfolder");
FileUtils.deleteDirectory(rootDir);
} catch (IOException e) {
e.printStackTrace();
}
}
}
위 코드를 실행하면 다음처럼 로그를 출력하면서 파일을 삭제합니다.
Remove file: /home/js/test/myfolder/myscript.sh
Remove file: /home/js/test/myfolder/folder3/folder4/text3.txt
Remove file: /home/js/test/myfolder/folder3/folder4/text2.txt
Remove file: /home/js/test/myfolder/folder3/folder4/text.txt
Remove file: /home/js/test/myfolder/folder3/folder4
Remove file: /home/js/test/myfolder/folder3/file6.txt
Remove file: /home/js/test/myfolder/folder3/file5.txt
Remove file: /home/js/test/myfolder/folder3
Remove file: /home/js/test/myfolder/folder2/file4.txt
Remove file: /home/js/test/myfolder/folder2/file3.txt
Remove file: /home/js/test/myfolder/folder2
Remove file: /home/js/test/myfolder/folder1/file2.txt
Remove file: /home/js/test/myfolder/folder1
Remove file: /home/js/test/myfolder/file1.txt
Remove file: /home/js/test/myfolder
다음과 같이 forEach에 인자로 전달한 Lambda 대신에 File::delete
를 사용할 수도 있습니다.
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
public class Example {
public static void main(String args[]) {
try {
File rootDir = new File("/home/js/test/myfolder");
Files.walk(rootDir.toPath())
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
} catch (IOException e) {
e.printStackTrace();
}
}
}
특정 파일만 삭제하도록 구현하려면 forEach에서 조건문을 추가하여 특정 파일만 삭제할 수도 있습니다.
References
Related Posts
- Java - Unsupported class file major version 61 에러
- Java - String.matches()로 문자열 패턴 확인 및 다양한 예제 소개
- Java - 문자열 공백제거 (trim, replace)
- Java - replace()와 replaceAll()의 차이점
- Java - ArrayList 초기화, 4가지 방법
- Java - 배열 정렬(Sorting) (오름차순, 내림차순)
- Java - 문자열(String)을 비교하는 방법 (==, equals, compare)
- Java - StringBuilder 사용 방법, 예제
- Java - 로그 출력, 파일 저장 방법 (Logger 라이브러리)
- Java IllegalArgumentException 의미, 발생 이유
- Java - NullPointerException 원인, 해결 방법
- Seleninum의 ConnectionFailedException: Unable to establish websocket connection 해결
- Java - compareTo(), 객체 크기 비교
- Java - BufferedWriter로 파일 쓰기
- Java - BufferedReader로 파일 읽기
- Java charAt() 함수 알아보기
- Java - BigInteger 범위, 비교, 연산, 형변환
- Java contains()로 문자(대소문자 X) 포함 확인
- Java - Set(HashSet)를 배열로 변환
- Java - 문자열 첫번째 문자, 마지막 문자 확인
- Java - 문자열 한글자씩 자르기
- Java - 문자열 단어 개수 가져오기
- Java - 1초마다 반복 실행
- Java - 배열을 Set(HashSet)로 변환
- Java - 여러 Set(HashSet) 합치기
- Java - 명령행 인자 입력 받기
- Java - 리스트 역순으로 순회, 3가지 방법
- Java - 특정 조건으로 리스트 필터링, 3가지 방법
- Java - HashMap 모든 요소들의 합계, 평균 계산
- Java - 특정 조건으로 HashMap 필터링
- Java - 싱글톤(Singleton) 패턴 구현
- Java - 숫자 왼쪽에 0으로 채우기
- Java - String 배열 초기화 방법
- Java - 정렬된 순서로 Map(HashMap) 순회
- Java - HashMap에서 key, value 가져오기