디렉토리 탐색 개요
Dart에서 파일 시스템을 탐색하는 방법은 매우 직관적이다. dart:io
패키지를 사용하여 파일과 디렉토리를 처리할 수 있으며, 이를 통해 파일을 읽고 쓰는 작업뿐만 아니라 디렉토리의 내용을 검색하는 작업도 수행할 수 있다.
Dart의 Directory
클래스는 파일 시스템의 디렉토리를 나타내며, 디렉토리 내의 파일과 서브 디렉토리를 쉽게 탐색할 수 있는 기능을 제공한다.
Directory 클래스 사용법
Directory
클래스는 다음과 같이 사용된다.
import 'dart:io';
void listDirectory(String path) {
var directory = Directory(path);
directory.list().forEach((entity) {
print(entity.path);
});
}
이 코드는 주어진 경로 path
에 있는 모든 파일과 디렉토리를 출력한다. directory.list()
메소드는 비동기적으로 Stream
을 반환하므로 디렉토리의 내용을 순차적으로 처리할 수 있다.
재귀적으로 디렉토리 탐색
때로는 하위 디렉토리까지 포함하여 재귀적으로 파일을 탐색해야 할 경우가 있다. 이를 위해서는 listSync()
메소드를 사용하여 동기 방식으로 디렉토리를 탐색할 수 있다.
void listAllFiles(String path) {
var directory = Directory(path);
directory.listSync(recursive: true).forEach((entity) {
print(entity.path);
});
}
위 코드에서 recursive: true
옵션을 주면 하위 디렉토리까지 탐색하여 그 안에 있는 파일 및 디렉토리 경로를 모두 출력할 수 있다.
특정 확장자 파일 검색
디렉토리를 탐색하는 과정에서 특정 확장자의 파일만 검색하고 싶을 때는, 파일의 경로에서 확장자를 검사하는 방법을 사용할 수 있다. Dart에서는 entity.path
를 통해 파일의 경로를 확인하고 이를 기반으로 확장자를 추출할 수 있다.
void listSpecificFiles(String path, String extension) {
var directory = Directory(path);
directory.listSync().forEach((entity) {
if (entity.path.endsWith(extension)) {
print(entity.path);
}
});
}
이 코드는 주어진 디렉토리에서 특정 확장자(예: .txt
)를 가진 파일만 출력한다.
디렉토리 존재 여부 확인
디렉토리를 탐색하기 전에 해당 경로가 실제로 존재하는지 확인하는 것은 매우 중요하다. 이를 위해 Directory
클래스의 existsSync()
메소드를 사용할 수 있다.
bool checkDirectoryExists(String path) {
var directory = Directory(path);
return directory.existsSync();
}
이 코드는 주어진 경로의 디렉토리가 존재하는지 여부를 true
또는 false
로 반환한다.
디렉토리 생성
파일 탐색을 하기 전에 원하는 경로에 디렉토리가 존재하지 않는다면 디렉토리를 생성해야 할 경우도 있다. Dart에서는 createSync()
메소드를 사용하여 동기적으로 디렉토리를 생성할 수 있다.
void createDirectory(String path) {
var directory = Directory(path);
if (!directory.existsSync()) {
directory.createSync();
print('Directory created: $path');
} else {
print('Directory already exists.');
}
}
위 코드는 지정한 경로에 디렉토리가 존재하지 않으면 새 디렉토리를 생성하고, 이미 존재하면 생성하지 않는다.
또한, 비동기 방식으로 디렉토리를 생성하고 싶을 때는 create()
메소드를 사용할 수 있다.
Future<void> createDirectoryAsync(String path) async {
var directory = Directory(path);
if (!await directory.exists()) {
await directory.create();
print('Directory created: $path');
} else {
print('Directory already exists.');
}
}
비동기 방식은 파일 시스템 작업이 완료되기를 기다리는 동안 다른 작업을 처리할 수 있어 더 효율적이다.
파일과 디렉토리 삭제
디렉토리나 파일을 삭제할 때는 deleteSync()
메소드를 사용한다. 이때, recursive: true
옵션을 주면 디렉토리 내 모든 파일과 서브 디렉토리를 재귀적으로 삭제할 수 있다.
void deleteDirectory(String path) {
var directory = Directory(path);
if (directory.existsSync()) {
directory.deleteSync(recursive: true);
print('Directory deleted: $path');
} else {
print('Directory does not exist.');
}
}
비동기 방식으로 삭제할 경우에는 delete()
메소드를 사용할 수 있다.
Future<void> deleteDirectoryAsync(String path) async {
var directory = Directory(path);
if (await directory.exists()) {
await directory.delete(recursive: true);
print('Directory deleted: $path');
} else {
print('Directory does not exist.');
}
}
이 코드들은 파일 시스템 내의 디렉토리나 파일을 안전하게 삭제하는 방법을 보여준다.
디렉토리의 경로 정보
Dart의 Directory
클래스는 여러 가지 유용한 경로 정보를 제공한다. 예를 들어, 사용자의 홈 디렉토리나 임시 디렉토리 경로를 얻을 수 있다.
void getDirectoryPaths() {
print('Temporary Directory: ${Directory.systemTemp.path}');
print('Current Directory: ${Directory.current.path}');
}
Directory.systemTemp
는 임시 파일을 저장할 수 있는 시스템의 임시 디렉토리 경로를 반환하며, Directory.current
는 현재 실행 중인 프로그램의 디렉토리 경로를 반환한다.
파일 시스템의 디렉토리 트리 시각화
여러 디렉토리를 재귀적으로 탐색할 때 그 구조를 시각화하여 보여줄 수 있다. Dart에서는 재귀적인 탐색을 통해 디렉토리 트리를 생성하고, 이를 콘솔에 출력할 수 있다.
void printDirectoryTree(String path, {String prefix = ''}) {
var directory = Directory(path);
if (directory.existsSync()) {
directory.listSync().forEach((entity) {
print('$prefix${entity.path}');
if (entity is Directory) {
printDirectoryTree(entity.path, prefix: '$prefix ');
}
});
}
}
이 함수는 지정된 경로를 재귀적으로 탐색하며, 디렉토리의 트리 구조를 보기 쉽게 출력해 준다. 이를 통해 파일 시스템의 디렉토리 구조를 시각적으로 이해하기 쉽다.
디렉토리의 메타데이터 접근
디렉토리뿐만 아니라 파일의 메타데이터 정보에도 접근할 수 있다. Dart에서는 파일과 디렉토리의 생성 날짜, 수정 날짜, 크기 등의 정보를 가져올 수 있다. 이를 위해서는 statSync()
또는 비동기적으로 stat()
메소드를 사용할 수 있다.
void printDirectoryMetadata(String path) {
var directory = Directory(path);
if (directory.existsSync()) {
var stats = directory.statSync();
print('Type: ${stats.type}');
print('Changed: ${stats.changed}');
print('Modified: ${stats.modified}');
print('Accessed: ${stats.accessed}');
} else {
print('Directory does not exist.');
}
}
위 코드에서 statSync()
메소드를 사용하여 디렉토리의 메타데이터에 동기적으로 접근한다. 이를 통해 디렉토리 또는 파일의 마지막 수정 시간, 접근 시간, 파일 유형 등을 확인할 수 있다.
비동기 방식으로 메타데이터를 얻고자 할 때는 다음과 같이 await
을 사용하여 처리할 수 있다.
Future<void> printDirectoryMetadataAsync(String path) async {
var directory = Directory(path);
if (await directory.exists()) {
var stats = await directory.stat();
print('Type: ${stats.type}');
print('Changed: ${stats.changed}');
print('Modified: ${stats.modified}');
print('Accessed: ${stats.accessed}');
} else {
print('Directory does not exist.');
}
}
심볼릭 링크 처리
파일 시스템 탐색 중에는 심볼릭 링크가 포함될 수 있다. 심볼릭 링크는 파일이나 디렉토리의 경로에 대한 참조이다. Dart의 Link
클래스를 사용하여 심볼릭 링크를 처리할 수 있다.
심볼릭 링크를 생성하는 예제는 다음과 같다.
void createSymbolicLink(String targetPath, String linkPath) {
var link = Link(linkPath);
link.createSync(targetPath);
print('Symbolic link created: $linkPath ->$targetPath');
}
이 코드는 targetPath
를 참조하는 심볼릭 링크를 linkPath
경로에 생성한다. 비동기 방식으로도 생성할 수 있다.
심볼릭 링크를 탐색할 때는 resolveSymbolicLinks()
메소드를 사용하여 실제 파일 경로를 확인할 수 있다.
void resolveLink(String linkPath) {
var link = Link(linkPath);
print('Resolved link: ${link.resolveSymbolicLinksSync()}');
}
비동기 방식의 경우는 resolveSymbolicLinks()
메소드를 await
하여 사용한다.
Future<void> resolveLinkAsync(String linkPath) async {
var link = Link(linkPath);
print('Resolved link: ${await link.resolveSymbolicLinks()}');
}
경로 조작
디렉토리 탐색을 할 때 경로를 조작하는 방법도 중요하다. Dart에서는 Path
클래스가 존재하지 않지만, Dart의 String
메소드를 사용하여 경로를 쉽게 다룰 수 있다. 파일 경로에서 파일명을 추출하거나 확장자를 제거하는 등의 작업을 String
메소드로 처리할 수 있다.
void manipulatePath(String filePath) {
print('Directory name: ${filePath.split(Platform.pathSeparator).last}');
print('File extension: ${filePath.split('.').last}');
}
이 코드는 경로에서 디렉토리 또는 파일명을 추출하고, 파일의 확장자를 가져오는 간단한 예이다.
경로 조작을 위한 패키지
경로를 보다 효율적으로 조작하기 위해 Dart에서는 path
패키지를 사용할 수 있다. 이 패키지를 사용하면 OS에 상관없이 플랫폼 간 호환성을 보장하며 경로를 처리할 수 있다.
import 'package:path/path.dart' as p;
void pathOperations(String filePath) {
print('Base name: ${p.basename(filePath)}');
print('Directory name: ${p.dirname(filePath)}');
print('Extension: ${p.extension(filePath)}');
}
이 코드는 path
패키지를 사용하여 파일의 경로에서 기본 이름, 디렉토리 이름, 확장자를 쉽게 추출한다. 이 패키지는 경로 관련 작업에서 매우 유용하다.