2013-12-17 6 views
1

Я только начал изучать C и пытаюсь сделать список путей. Я попытался перечислить путь в каталоге с помощью dirent и попытался проверить, является ли результат файлом или каталогом, используя stat. Однако, даже если путь является файлом, он вернет каждый путь в качестве каталога.Проверка того, является ли путь файлом или каталогом

Это мой код:.
[Edit]

#include <stdio.h> 
    #include <sys/stat.h> 
    #include <sys/types.h> 
    #include <dirent.h> 

    int main(void) 
    { 
     DIR *mydir = opendir("/Library/Logs"); 
     char path[250]; 
     struct dirent *entry = NULL; 
     struct stat buf; 

     while((entry = readdir(mydir))) /* If we get EOF, the expression is 0 and 
             * the loop stops. */ 
     { 
      snprintf(path, 250, "%s",entry->d_name); 
      stat(path,&buf); 
      if(S_ISDIR(buf.st_mode)) 
       printf("D: %s\n", path); 
      else if (S_ISREG(buf.st_mode)) 
       printf("F: %s\n", path); 
      else 
       printf("O: %s\n", path); 
     } 
} 
+1

Если вы проверили 'ли стат() удалось', вы обнаружите, что она не каждый раз, если вы не находитесь в '/ Library/Logs' в качестве рабочего каталога. И вы не можете анализировать возвращенные данные из отказавшего системного вызова; вы ничего не можете сказать об информации в 'buf', за исключением того, что она похожа на запись в каталоге (но это просто случайно). См. [Joe] (http://stackoverflow.com/users/57135/joe) [ответ] (http://stackoverflow.com/a/20625123/15168) для краткого изложения того, что вам еще нужно, чтобы делать. Но проверка результата каждого системного вызова - хорошее начало. –

ответ

3
stat(entry->d_name,&buf); 

На данный момент, вы не имеете никакого контекста о каталоге вы смотрите в

Вы будете необходимо создать буфер и объединить directory/filename, прежде чем звонить stat (с использованием strcat или snprintf)

Проверка обратного вызова stat - если отличное от нуля, посмотрите на errno, чтобы узнать, что пошло не так. Я предполагаю, что в настоящее время он сообщает об этом ENOENT.

+0

Привет, я новичок в c, поэтому простите меня, если я получу что-то не так. Поэтому я могу попытаться создать буфер char [250] и strcat для конкатенации пути до вызова функции stat? – user2541163

+0

Да, хотя было бы проще использовать snprintf (используя '% s /% s' в качестве формата). – Joe

+0

OK попробует это позже. Спасибо – user2541163

0

Попробуйте это, используя READDIR и Dirent

#include <stdlib.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <string.h> 
#include <errno.h> 
/* "readdir" etc. are defined here. */ 
#include <dirent.h> 
/* limits.h defines "PATH_MAX". */ 
#include <limits.h> 

/* List the files in "dir_name". */ 

static void 
list_dir (const char * dir_name) 
{ 
    DIR * d; 

    /* Open the directory specified by "dir_name". */ 

    d = opendir (dir_name); 

    /* Check it was opened. */ 
    if (! d) { 
     fprintf (stderr, "Cannot open directory '%s': %s\n", 
       dir_name, strerror (errno)); 
     exit (EXIT_FAILURE); 
    } 
    while (1) { 
     struct dirent * entry; 
     const char * d_name; 

     /* "Readdir" gets subsequent entries from "d". */ 
     entry = readdir (d); 
     if (! entry) { 
      /* There are no more entries in this directory, so break 
       out of the while loop. */ 
      break; 
     } 
     d_name = entry->d_name; 
     /* Print the name of the file and directory. */ 
     printf ("%s/%s\n", dir_name, d_name); 

     /* See if "entry" is a subdirectory of "d". */ 

     if (entry->d_type & DT_DIR) { 

      /* Check that the directory is not "d" or d's parent. */ 

      if (strcmp (d_name, "..") != 0 && 
       strcmp (d_name, ".") != 0) { 
       int path_length; 
       char path[PATH_MAX]; 

       path_length = snprintf (path, PATH_MAX, 
             "%s/%s", dir_name, d_name); 
       printf ("%s\n", path); 
       if (path_length >= PATH_MAX) { 
        fprintf (stderr, "Path length has got too long.\n"); 
        exit (EXIT_FAILURE); 
       } 
       /* Recursively call "list_dir" with the new path. */ 
       list_dir (path); 
      } 
     } 
    } 
    /* After going through all the entries, close the directory. */ 
    if (closedir (d)) { 
     fprintf (stderr, "Could not close '%s': %s\n", 
       dir_name, strerror (errno)); 
     exit (EXIT_FAILURE); 
    } 
} 

int main() 
{ 
    list_dir ("/Library/Logs"); 
    return 0; 
} 

Выход будет

/Library/Logs/.<br /> 
/Library/Logs/..<br /> 
/Library/Logs/somedir001<br /> 
/Library/Logs/somedir002 
+0

Привет, я пробовал использовать ваши, и мне нравится тот факт, что он рекурсивный (это то, что я планирую делать). Однако, когда я достигаю пути к файлу, который начинается с ./, он вернет мне ошибку с разрешенным разрешением и остановит всю программу. – user2541163

+0

Элемент 'd_type'' struct dirent' отсутствует во всех системах (это не требуется POSIX) , и на тех, где он присутствует, он не всегда поддерживается во всех файловых системах. Поэтому рекомендуется использовать 'stat (2)' для каждой записи каталога, если вы точно не знаете, что ваша ОС и файловая система поддерживают элемент 'd_type'. –

+0

@AdamRosenfield Привет, я понимаю, что вы говорите, но если бы я хотел, чтобы этот код реализовал stat (2), как вы упомянули, как это можно сделать? Я понятия не имею, как его использовать. Извините за плохое понимание языка – user2541163

Смежные вопросы