2010-08-21 2 views
1

Программа предназначена для открытия каталога и отображения имени файла ... ie, если есть файл .. он должен сказать FILE .... else DIRECTORY .. , но программа отображает все файлы, как каталог ..Доступ к каталогам в C

может кто-нибудь пожалуйста проверить код на наличие ошибок .... Thnx

#include<stdio.h> 
#include<dirent.h> 
#define DIR_path "root/test"  
main() 
{ 
    DIR *dir; 
    dir=opendir(DIR_PATH); 
    printf("THe files inside the directory :: \n"); 

    struct dirent *dent; 
    if(dir!=NULL) 
    { 

     while((dent=readdir(dir))) 
     { 
      FILE *ptr; 
      printf(dent->d_name); 

       if(ptr=fopen(dent->d_name,"r")) 
       { 
        print("\tFILE\n"); 
        fclose(ptr); 
       } 
       else 
        printf("\t DIRECTORY\n"); 
     } 
      close(dir); 
    } 
    else 
      printf("ERROR OPENIN DIRECTORY"); 

} 
+1

Возможные контратип http://stackoverflow.com/questions/1542763/what-is-the-correct-way-to-use-the-stat-function-to-test-if-a-dirent -is-a-directc, http://stackoverflow.com/questions/3029633/how-to-use-dirent-h-correctly и/или http://stackoverflow.com/questions/1271064/how-do- я-Проходной-все-файлы-в-папки-с помощью-с. Кстати, это самое уродливое диритарное использование, которое я когда-либо видел. См. Ссылки по этой причине. – rubenvb

ответ

9

Одна проблема заключается в том, что каталог также тип файла, и может быть нормально fopen() ed. Вы хотите вызвать lstat() на каждый файл, чтобы проверить, является ли он каталогом. Пример:

struct stat st; 
lstat(dent->d_name, &st); 
if(S_ISDIR(st.st_mode)) 
    printf("\t DIRECTORY\n"); 
else 
    printf("\t FILE\n"); 

Но эта ошибка должна привести к тому, что все записи будут отображаться в виде файлов. У вас есть разрешения на чтение файлов в этом каталоге? Каково значение errno после звонка fopen()?

+0

На самом деле, вы, вероятно, захотите проверить код возврата ** lstat() ** на наличие ошибок. В цикле * readdir() * это маловероятно, но возможно. – NVRAM

0

Предположим, что root/test содержит файл foo. Вызов dent=readdir(dir) устанавливает dent->d_name на "foo". У вас уже есть отладочный вывод, который показывает это: printf(dent->d_name) ¹. Затем вы пытаетесь открыть foo с fopen, но файл на самом деле root/test/foo. Таким образом, это терпит неудачу каждый раз (кроме случаев, когда у вас также есть файл с именем foo в текущем каталоге).

Есть два способа открыть нужный файл:

  • Construct полного имени файла, сцеплению аргумента opendir с именем файла. Что-то вроде:

    /*before */ 
    size_t dir_length = strlen(DIR_PATH); 
    char *filename = malloc(dir_length + NAME_MAX + 2); /*error checking omitted*/ 
    strcpy(filename, DIR_PATH); 
    filename[dir_length] = '/'; 
    filename[dir_length+1] = 0; 
    while ((dent = readdir(dir)) != NULL) { 
        strcpy(filename + dir_length + 1, dent->d_name); 
        /*now call lstat, fopen, etc. on filename*/ 
    
  • Перейдите в каталог, в котором находитесь объекты. Например, изменить opendir вызов

    chdir(DIR_PATH); /*error checking omitted*/ 
    dir = opendir("."); 
    

    Вы должны помнить, чтобы сохранить предыдущую директорию с getcwd и chdir вернуться к нему позже. Этот метод не рекомендуется в производственном программном обеспечении, потому что возможно иметь текущий каталог, который вы не можете вернуть chdir из-за разрешений.

slacker has already explained why fopen can't be used to test if a file is a directory.

¹ который, кстати, должен быть puts(dent->d_name) или даже лучше fputs(dent->d_name, stderr): оригинал printf вызов будет разорвать, если имя файла содержит %, который не является большой проблемой для отладки вывода, но это плохая привычка.

0

его комбинация из двух ответов бездельника и Жиля. используйте lstat, но не используйте его, как сказал slacker. Вам нужно отправить lstat полный путь, а не только dent-> d_name. И просто чтобы вы знали, что lstat требует, чтобы вы включили sys/stat.h>
, если вы посмотрите на страницу man для lstat, есть тестовая программа внизу или просто посмотрите на мою.

Это моя программа, которая пытается имитировать «ls» на linux.Примечание: цвета escape-последовательности не работают в окнах, если вы беспокоитесь о переносимости.

#include <iostream> 
#include <dirent.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 

int main(int argc,char* argv[]){ 
char blue[] = { 0x1b, '[', '1', ';', '3', '4', 'm', 0 }; 
char normal[]={ 0x1b, '[', '0', ';', '3', '9', 'm', 0 }; 
char green[]= { 0x1b, '[', '0', ';', '3', '2', 'm', 0 }; 
char red[]= { 0x1b, '[', '0', ';', '3', '1', 'm', 0 }; 
char cyan[]= { 0x1b, '[', '0', ';', '3', '6', 'm', 0 }; 
DIR* myDirectory; 
char *path=NULL; 
size_t size=100; 
int result; 
char* fullpath; 
if (argc >=3){ 
    std::cout<<"Usage: myls <path>"<<std::endl; 
    return -1; 
} 
if (argc >= 2){ 
    myDirectory=opendir(argv[1]); 
    if (errno==ENOENT){ 
    std::cout<<"error: file does not exist"<<std::endl; 
    return -1; 
    } 
    path=argv[1]; 
if (path[strlen(path)-1]!='/') 
strcat(path,"/"); 
} 
else if(argc==1){ 
    path=getcwd(path,size); 
    strcat(path,"/"); 
    myDirectory=opendir(path); 
} 
struct stat fileProperties; 
struct dirent* directory; 
do{ 
    directory=readdir(myDirectory); 
    if (directory!=NULL){ 
    fullpath=new char[strlen(path)+strlen(directory->d_name)+2]; 
    strcat(fullpath,path); 
    strcat(fullpath,directory->d_name); 
    result=lstat(fullpath,&fileProperties); 
    //std::cout<<result<<fullpath; 
    switch (fileProperties.st_mode & S_IFMT){ 
     case S_IFDIR: std::cout<<blue; 
      break; 
     case S_IFLNK: std::cout<<cyan; break; 
     case S_IFREG: std::cout<<normal; 
     default: std::cout<<normal; 
     if (fileProperties.st_mode & S_IXUSR) 
      std::cout<<green; 
     break; 
     } 

     std::cout<<directory->d_name<<"\n"; 
     std::cout<<normal; 
    } 
    }while(directory!=NULL); 
    std::cout<<normal<<'\n'; 
    closedir(myDirectory); 
    delete[] fullpath; 
    return 0; 
}