여기서는 아주 간단한 형태의 ls 명령을 구현하려고 한다. ls라 함은 리눅스 환경에서 디렉토리(or 폴더)의 내용을 보는 명령을 의미한다. 그리고 이런 ls 명령의 아주 간단한 형태는 단순하게 내부에 있는 파일들/디렉토리들의 이름들을 공백을 기준으로 출력하는 것을 말한다.
먼저 scandir() 함수에 대한 소개를 먼저 하려고 한다.
#include <dirent.h>
int scandir(const char *dirp, struct dirent ***namelist,
int (*filter)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **));
scandir() 함수는 인자로 dirp에 디렉토리 이름을 주면 해당 디렉토리에 있는 모든 파일 및 디렉토리 목록을 함수포인터 형태로 넘겨준 filter 함수에서 거르고 compar 함수의 비교 조건을 기준으로 정렬하여 결과를 namelist에 동적할당해서 넣어주는 함수이다. 반환값은 디렉토리 내부에 있는 파일/디렉토리 개수이다. 이 함수를 사용하면 파일명/디렉토리명을 알파벳 순서 대로, 혹은 생성 시간 순서 대로 정렬하거나 filter()로 특정 규칙의 파일/디렉토리만 가져올 수도 있다. scandir() 함수에 대한 자세한 내용은 리눅스에서 "man scandir"이라고 타이핑하면 볼 수 있으므로 이 정도에서 설명을 마치겠다.
만약 filter를 사용하지 않으려면 filter에 NULL을 넘겨주면 된다. 그리고 compar의 경우 이름을 기준으로 정렬할 것이므로 라이브러리 내 이미 구현된 alphasort를 사용하도록 하겠다.
위에서 설명한 내용을 기반으로 scandir에 대한 아주 간단한 사용을 보자면 아래와 같다. 이 코드는 name_list에 scandir을 사용하여 현재 디렉토리의 내용들을 가져오는 코드다. name_list는 scandir에 의해 동적할당 되므로 종료 하기 전에 name_list들이 가리키는 모든 메모리와 name_list를 free() 함수를 사용하여 할당 해제 해줘야 한다. 여기서는 SAFE_FREE라는 매크로를 정의하여 혹시 모를 오류를 방지했다.
#include <stdlib.h>
#include <dirent.h>
#define SAFE_FREE(p) {if(p!=NULL){free(p);p=NULL;}}
int main()
{
int i = 0;
int name_count = 0;
struct dirent** name_list = NULL;
name_count = scandir(".", &name_list, NULL, alphasort);
for (i = 0; i < name_count; i++) {
SAFE_FREE(name_list[i]);
}
SAFE_FREE(name_list);
return 0;
}
이제 위 코드를 이해했다고 가정하면 dirent 구조체의 내용을 알고 있기만 하면 ls 명령의 기본적인 형태를 작성할 수 있을 거라 생각된다. dirent 구조체의 내용은 아래와 같으며 ls 명령을 구현하는 데 필요한 정보는 d_name 필드이다.
struct dirent
{
long d_ino; // 아이노드
off_t d_off; // dirent의 offset
unsigned short d_reclen; // d_name의 길이
char d_name [NAME_MAX+1]; // 파일/디렉토리 이름
}
우리는 디렉토리/파일 이름들을 공백을 기준으로 출력하고자 하는 것이기에 결론적으로 d_name을 공백을 두고 반복해서 출력하면 된다. name_count만큼. 그리고 이것을 위 코드에 덧붙이면 아래와 같다
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#define SAFE_FREE(p) {if(p!=NULL){free(p);p=NULL;}}
int main()
{
int i = 0;
int name_count = 0;
struct dirent** name_list = NULL;
name_count = scandir(".", &name_list, NULL, alphasort);
for (i = 0; i < name_count; i++) {
printf("%s ", name_list[i]->d_name);
SAFE_FREE(name_list[i]);
}
printf("\n");
SAFE_FREE(name_list);
return 0;
}
.
'리눅스 > 프로그래밍' 카테고리의 다른 글
[리눅스] 심플하게 구현하는 echo 명령어(command) (0) | 2020.11.07 |
---|---|
[리눅스]리눅스 C언어 개발환경 갖추고 샘플 프로그램 실행해보기(+ GCC, Vim, Make) (0) | 2020.04.28 |
댓글