차근차근/C

재귀호출,디렉토리검색

예쁜꽃이피었으면 2014. 10. 22. 12:24

검색어 : 재귀호출,디렉토리검색


http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/Code/C/Scandir


설명 

디렉토리에 있는 모든 파일들을 검사하는 함수 입니다. 검사된 파일을 위한 작업을 위해서 함수 포인터를 등록해서 사용하도록 작성되어 있으며, 디렉토리 깊이 검사를 위한 기능도 포함되어 있습니다.

사용방법 

다음은 함수 선언입니다.
Scandir(char *cwd, void(*func)(char *), int depth)
  1. cwd : 검색하고자 하는 경로명
  2. func : 함수 포인터, 인자는 파일이름이 주어진다.
  3. depth : 디렉토리 검색 깊이. 0이면 모든 하위디렉토리를 전부 검색, 0보다 크면 해당 인수의 깊이 만큼만 검색 

다음은 사용 예입니다.
// 단순 출력한다.
void myfunc(char *file)
{
    print("--> %s\n", file);
}

int main()
{
    // home디렉토리에 있는 모든 파일과 그 하부디렉토리의 파일을
    // 검색한후 myfunc를 호출해서 단순 출력한다.
    Scandir("/home", myfunc, 0);
}

코드 

#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

static int  indent = 0;

char cdir[256];
void myfunc(char *file)
{
    printf("%s/%s\n", getcwd(cdir, 256),file);
}

void Scandir(char *wd, void (*func)(char *), int depth)
{
    struct dirent **items;
    int nitems, i;
    // 인자로 받은 디렉토리로 이동한다.
    if (chdir(wd) < 0)
    {
        printf("DIR : %s\n", wd);
        perror("chdir ");
        exit(1);
    }

    // scandir 함수를 이용해서 현재 디렉토리의
    // 모든 파일과 디렉토리의 내용을 가져온다.
    nitems = scandir(".", &items, NULL, alphasort);

    // 디렉토리(파일포함) 항목의 갯수만큼 루프를 돌리며 
    // 만약 해당 파일이 디렉토리 일경우
    // Scandir 함수를 재귀 호출한다.
    for (i = 0; i < nitems; i++)
    {
        // 파일 상태를 저장하기 위한 구조체
        struct stat fstat;

        // 현재디렉토리, 이전디렉토리 는 무시한다.
        if ( (!strcmp(items[i]->d_name, ".")) || (!strcmp(items[i]->d_name, "..")) )
        { 
            continue;
        }

        // 함수포인터를 호출한다. 인자로 검색한 파일이름이 넘어간다. 
        func(items[i]->d_name);

        // 만약 파일이 디렉토리 이라면
        // Scandir 을 재귀 호출한다.
        // 그리고 디렉토리의 depth 레벨을 1 증가 한다.
        lstat(items[i]->d_name, &fstat);
        if ((fstat.st_mode & S_IFDIR) == S_IFDIR)
        {
            // depth만큼만 하부 디렉토리검색을 한다.
            // 0일 경우 깊이에 관계없이 검색한다.
            if (indent < (depth-1) || (depth == 0))
            {
                   indent ++;
                 Scandir(items[i]->d_name, func, depth);
            }
        }
    }
    // 디렉토리의 depth 레벨을 1 감소시키고
    // 하위 디렉토리로 이동한다.
    indent --;
    chdir("..");
}


반응형