리눅스/유닉스 계열에서 디렉토리의 모든 파일 리스트를 얻는 기능을 구현하려고 할 때 fts
라이브러리를 이용하면 됩니다.
- fts_open(): 인자로 전달된 디렉토리에 대한 FTS 객체를 리턴합니다.
- fts_read(): FTS 객체에서 파일에 대한 FTSENT 객체를 리턴합니다.
처음 본 라이브러리를 예제로 만들어본 것이기 때문에, 설명이 부족할 수 있습니다. 참고해서 봐주세요. 먼저 예제 코드 및 출력 결과를 보고, 그 이후에 부분적으로 살펴보겠습니다.
예제
다음 예제는 "./"
디렉토리에 대한 모든 파일을 출력합니다. fts라이브러리는 recursive로 폴더를 순회하며 파일들을 모두 찾아냅니다.
예제는 안드로이드 프레임워크 코드를 참고하여 작성하였습니다.
main.cpp
#include <errno.h>
#include <string.h>
#include <fts.h>
#include <iostream>
using namespace std;
int main() {
std::string path("./");
FTS *fts;
char *argv[] = { (char*) path.c_str(), nullptr };
if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) {
if (errno != ENOENT) {
cout << "Failed to fts_open " << path;
}
return -1;
}
FTSENT *p;
while ((p = fts_read(fts)) != nullptr) {
switch (p->fts_info) {
case FTS_DP:
cout << "Directory: " << p->fts_path << "\n";
break;
case FTS_F:
cout << "File: " << p->fts_path << "\n";
break;
case FTS_SL:
case FTS_SLNONE:
cout << "Symbolic link: " << p->fts_path << "\n";
break;
}
}
fts_close(fts);
return 0;
}
Build & Run
코드를 실행하기 전에 현재 디렉토리 상태는 다음과 같습니다.
$ tree
.
├── aa
│ └── file2.txt
├── bb
│ ├── dd
│ │ ├── file6.txt
│ │ └── file7.txt
│ ├── file3.txt
│ ├── file4.txt
│ └── file5.txt
├── cc
│ ├── file8.txt
│ ├── file9.txt
│ └── symbolic.txt -> file8.txt
├── file1.txt
├── main.cpp
└── main
다음 명령어로 빌드 및 실행을 하였습니다.
$ g++ main.cpp -o main
$ ./main
결과를 보시면 "./"
아래의 모든 파일들이 출력되었습니다.
File: ./bb/file5.txt
File: ./bb/dd/file7.txt
File: ./bb/dd/file6.txt
Directory: ./bb/dd
File: ./bb/file3.txt
File: ./bb/file4.txt
Directory: ./bb
File: ./aa/file2.txt
Directory: ./aa
Symbolic link: ./cc/symbolic.txt
File: ./cc/file9.txt
File: ./cc/file8.txt
Directory: ./cc
File: ./file1.txt
File: ./main.cpp
File: ./main
Directory: ./
fts_open()
다음 처럼 fts_open()을 사용하여 FTS 객체를 얻을 수 있으며, 실패에 대한 예외처리를 할 수 있습니다. 인자로 파일 패스가 전달됩니다.
std::string path("./");
char *argv[] = { (char*) path.c_str(), nullptr };
if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) {
if (errno != ENOENT) {
cout << "Failed to fts_open " << path;
}
return -1;
}
옵션에 대한 의미는 다음과 같습니다. 더 자세한 것은 manpage를 확인해주세요.
- FTS_PHYSICAL : This option causes the fts routines to return FTSENT structures for symbolic links
- FTS_NOCHDIR : To allow descending to arbitrary depths and improve performance
- FTS_XDEV : This option prevents fts from descending into directories that have a different device number
fts_read()
다음 처럼 fts_read()를 이용하여 디렉토리를 순회할 수 있습니다. FTSENT의 fts_path
로 파일 패스를 얻을 수 있습니다.
FTSENT *p;
while ((p = fts_read(fts)) != nullptr) {
switch (p->fts_info) {
case FTS_DP:
cout << "Directory: " << p->fts_path << "\n";
break;
case FTS_F:
cout << "File: " << p->fts_path << "\n";
break;
case FTS_SL:
case FTS_SLNONE:
cout << "Symbolic link: " << p->fts_path << "\n";
break;
}
}
FTSENT의 구조는 다음과 같습니다.
typedef struct _ftsent {
int fts_info; /* status for FTSENT structure */
char *fts_accpath; /* access path */
char *fts_path; /* root path */
size_t fts_pathlen; /* strlen(fts_path) */
char *fts_name; /* file name */
size_t fts_namelen; /* strlen(fts_name) */
long fts_level; /* depth (-1 to N) */
int fts_errno; /* file errno */
long long fts_number; /* local numeric value */
void *fts_pointer; /* local address value */
struct ftsent *fts_parent; /* parent directory */
struct ftsent *fts_link; /* next file structure */
struct ftsent *fts_cycle; /* cycle structure */
struct stat *fts_statp; /* stat(2) information */
} FTSENT;
그리고 위의 예제에서 사용한 FTS 파일 정보들은 다음과 같습니다. 더 자세한 것은 manpage를 확인해주세요.
- FTS_DP : Directory 파일
- FTS_F : 일반적인 파일
- FTS_SL, FTS_SLNONE : Symbolic link 파일
fts_close()
FTS를 모두 사용하였으면 다음 코드로 close하면 됩니다.
fts_close(fts);
참고
Loading script...
Related Posts
- Ubuntu/Linux - 특정 이름이 들어간 파일 모두 찾고 삭제하기
- Ubuntu/Linux - 특정 이름이 포함된 프로세스 모두 종료
- Ubuntu/Linux - 사용자 계정 이름 확인 (id, whoami)
- Ubuntu/Linux - E: unable to locate package 에러 해결
- Ubuntu 22.04/20.04 - Yarn 설치 방법
- Linux/Ubuntu - grep 명령어로 문자열 검색
- Linux/Ubuntu - 터미널에서 seq로 명령어 N회 반복
- Linux/Ubuntu - wc 명령어로 Line(줄) 개수 세기
- bash: pip: command not found 문제 해결 (Linux/Ubuntu)
- Ubuntu 22.04 - Swap 메모리 늘리기
- Linux - 파일이 수정된 날짜/시간 확인 방법
- Linux - 파일, 디렉토리 삭제 명령어(rm -rf, rmdir)
- 우분투 22.04 - deb 파일 설치하기
- Ubuntu 20.04 - OpenJDK 11 설치, 삭제
- Linux - ps 명령어로 실행 중인 프로세스(PID) 확인
- Ubuntu 20.04 - SSH 설치와 접속 방법
- Ubuntu에서 PPA 저장소 추가, 제거 방법
- Ubuntu 22.04 - Brave 브라우저 설치
- Ubuntu 22.04 - 프로스트와이어(FrostWire) 설치
- Ubuntu 22.04 - Remmina 설치 방법
- Ubuntu 22.04 - Rust 설치하기
- Ubuntu 22.04 - 텔레그램 설치하기
- Ubuntu - Deluge 토렌트 클라이언트 설치
- Ubuntu JDK 17 (OpenJDK) 설치, 삭제
- Ubuntu 20.04 스팀(Steam) 설치 방법
- Ubuntu에서 draw.io 설치하는 방법
- 우분투에 VMware 설치하기
- [Ubuntu] VMware에서 Windows 11 설치
- Vi/Vim에서 1줄 또는 여러줄 삭제 방법
- Vi/Vim에서 라인 번호 표시하 기
- 우분투에서 rar 압축, 압축 풀기
- Ubuntu에서 구글 드라이브 사용하기 (로컬 폴더에 마운트)
- [Ubuntu] apt-cache search, 설치 가능한 패키지 검색
- Ubuntu - DNS 캐시 삭제 방법
- Ubuntu에서 사용할 수 있는 Text Editor 소개