2010-04-23 2 views
1

파일에 중복 여부를 확인하는 함수를 작성했습니다. 이 함수 서명은 다음과 같습니다C (Linux)에서 디렉토리를 통해 파일을 반복하고 "저장"하는 가장 좋은 방법은 무엇입니까?

int check_dup_memmap(char *f1_name, char *f2_name) 

이 반환

  • (-1) - 뭔가 잘못된 경우;
  • (0) - 두 파일이 비슷한 경우;
  • (+1) - 두 파일이 다른 경우.

다음 단계는 특정 디렉토리의 모든 파일을 반복하고 이전 기능을 적용하고 기존의 모든 중복에 대한 보고서를 제공하는 기능을 작성하는 것입니다.

처음에는 특정 디렉토리의 모든 파일 이름을 가진 파일을 생성 한 다음 해당 파일을 다시 읽고 두 파일을 모두 비교하여 비교하는 함수를 작성하려고 생각했습니다. 다음은 특정 디렉토리의 모든 파일 이름을 가져 오는 함수 버전입니다. 내가 다시하고 다시 파일을 구문 분석 할 필요로

void *build_dir_tree(char *dirname, FILE *f) 
{ 
    DIR *cdir = NULL; 
    struct dirent *ent = NULL; 
    struct stat buf; 
    if(f == NULL){ 
     fprintf(stderr, "NULL file submitted. [build_dir_tree].\n"); 
     exit(-1); 
    } 
    if(dirname == NULL){ 
     fprintf(stderr, "NULL dirname submitted. [build_dir_tree].\n"); 
     exit(-1); 
    } 
    if((cdir = opendir(dirname)) == NULL){ 
     char emsg[MFILE_LEN]; 
     sprintf(emsg, "Cannot open dir: %s [build_dir_tree]\t",dirname); 
     perror(emsg); 
    } 
    chdir(dirname); 
    while ((ent = readdir(cdir)) != NULL) { 
     lstat(ent->d_name, &buf); 
     if (S_ISDIR(buf.st_mode)) { 
      if (strcmp(".", ent->d_name) == 0 || 
        strcmp("..", ent->d_name) == 0) { 
       continue; 
      } 
      build_dir_tree(ent->d_name, f); 
     } 
     else{ 
      fprintf(f, "/%s/%s\n",util_get_cwd(),ent->d_name); 
     } 
    } 
    chdir(".."); 
    closedir(cdir); 
} 

아직도 나는이 방법이 조금 비효율적 고려한다. 당신의 의견에

다른 방법은 내가 무엇을 따라야됩니다

  • 이 자료 구조를 작성하고 파일을 작성하는 파일을 대신 잡아? 나는 파일이 많은 디렉토리에 대해 메모리가 매우 단편화 될 것이라고 생각한다.
  • 자동 확장 배열에서 모든 파일 이름을 유지하면 인접한 메모리 위치에 있기 때문에 인덱스별로 모든 파일에 쉽게 액세스 할 수 있습니다.
  • mmap()을 사용하여 메모리에서이 파일을 매핑 하시겠습니까? 그러나 mmap은 파일이 커질수록 실패 할 수 있습니다.

이에 대한 의견. 가장 효율적인 경로를 선택하고 최대한 적은 리소스로 액세스하려고합니다. 이것은 프로그램의 요구 사항입니다 ...

EDIT : 특정 디렉토리의 파일 수를 반복하지 않고도 얻을 수있는 방법이 있습니까?

+0

왜 모든 항목을 조작하기 전에 모든 항목을 읽으려고합니까? 나는 당신의 디렉토리 읽기 함수를 for_each 함수로 바꿀 것이다.이 함수는 디렉토리 이름과 함수 포인터 그리고 void * 인자를 전달한다. 이 함수는 char * 인수를 취하여 읽기 디렉토리 이름 (또는 파일을 열어 FILE 또는 fd를 전달할 수 있음)과 void *를 취할 수 있습니다. 이 함수는 compare 함수를 호출합니다. – nategoose

답변

3

아마도 해시 또는 체크섬을 사용하려고합니다. 각 파일 내용의 해시를 만들고 각 해시를 해당 해시가있는 파일 이름 목록과 연결하십시오. 그런 다음 해시를 구성하면 다른 파일이 같은 해시를 공유하는지 확인할 수 있습니다. 충돌이 발생한 경우에만 실제로 전체 파일을 비교해야합니다. 좋은 해시 함수를 선택하면 충돌은 비교적 드물어 전체 비교는 드뭅니다.

해시의 크기와 충돌 수 사이에는 트레이드 오프가 있음에 유의하십시오. 더 작은 해시를 사용하면 충돌이 더 자주 발생하지만 파일 당 더 적은 공간을 사용하게되며 더 큰 해시를 사용하면 전체 파일 비교는 적게 수행해야합니다. 더 큰 해시를 비교하십시오. 또한 일부 해시 함수는 다른 해시보다 충돌이 적지 만 일부 더 우수한 해시 함수는 빈약 한 해시 함수보다 시간이 오래 걸리고 계산 집약적 일 수 있습니다.

효과적인 파일 및 디렉토리 탐색 방법은 ftw 또는 nftw입니다.

+0

제 의견으로는 해시가 필요하지 않습니까? 여전히 문제는 파일 이름을 저장하는 방법입니다. 어떤 유형의 데이터 구조입니까? –

+0

@Andrei, 해시 테이블을 사용하여 파일의 해시를 문자열의 링크 목록에 매핑합니다. 각 문자열에는 파일 경로가 들어 있습니다. –

+1

해시가 없으면 복제본을 어떻게 확인하겠습니까? 각 파일의 전체 파일 내용을 디렉토리의 다른 모든 파일의 전체 파일 내용과 비교합니까? 물론, 파일 크기가 첫 번째 경우와 같은지 먼저 확인할 수 있습니다. (여기에도 같은 크기의 300k + 파일이있는 디렉토리가 있지만) 모든 파일을 한 번 해시하는 것과 비교하면 매우 느릴 것입니다. 충돌이 있으면 한 번 콘텐츠. – nos

관련 문제