访问 C 中的目录

发布于 2024-09-15 13:18:52 字数 789 浏览 6 评论 0原文

该程序是打开一个目录并显示文件名...... 即如果有一个文件..它应该说文件....否则目录.. 但程序将所有文件显示为目录..

任何人都可以检查代码是否有任何错误....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");

}

The program is to open a directory and to display the name of the files...
i.e if there is a file..it should say FILE....else DIRECTORY..
but the program displays all the files as directory..

Could anyone pls check the code for any errors....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");

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

定格我的天空 2024-09-22 13:18:52

一个问题是目录也是一种文件类型,并且可以正常fopen()编辑。您想要对每个文件调用 lstat() 来检查它是否是一个目录。像这样:

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

但是这个错误应该导致所有条目都显示为文件。您对该目录下的文件有读取权限吗? fopen() 调用后 errno 的值是多少?

One problem is that a directory is also a type of file, and can be normally fopen()ed. You want to call lstat() on each file to check whether it is a directory. Like this:

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

But this error should lead to all entries being displayed as files. Do you have read permissions for the files in this directory? What is the value of errno after the fopen() call?

峩卟喜欢 2024-09-22 13:18:52

假设 root/test 包含一个名为 foo 的文件。对 dent=readdir(dir) 的调用将 dent->d_name 设置为 "foo"。您已经有了显示以下内容的调试输出:printf(dent->d_name)¹。然后您尝试使用 fopen 打开 foo,但该文件实际上是 root/test/foo。所以每次都会失败(除非当前目录中碰巧还有一个名为 foo 的文件)。

有两种方法可以打开正确的文件:

  • 通过将 opendir 的参数与文件名连接来构造文件的完整名称。类似于:

    <前><代码>/*之前*/
    size_t dir_length = strlen(DIR_PATH);
    char *文件名 = malloc(dir_length + NAME_MAX + 2); /*错误检查省略*/
    strcpy(文件名,DIR_PATH);
    文件名[目录长度] = '/';
    文件名[目录长度+1] = 0;
    while ((dent = readdir(dir)) != NULL) {
    strcpy(文件名 + dir_length + 1, dent->d_name);
    /*现在对文件名调用 lstat、fopen 等*/

  • 更改为您列出的目录。例如,将 opendir 调用更改为

    chdir(DIR_PATH); /*错误检查省略*/
    dir = opendir(".");
    

    您必须记住使用 getcwdchdir 保存之前的目录。在生产软件中不建议使用此方法,因为由于权限的原因,您可能无法 chdir 返回当前目录。

slacker已经解释了为什么fopen不能用于测试如果文件是目录。


¹ 顺便说一下,应该是 puts(dent->d_name) 甚至更好的 fputs(dent->d_name, stderr):你原来的 printf<如果文件名包含 % , /code> 调用就会中断,这对于调试输出来说不是一个大问题,但却是一个坏习惯。

Suppose that root/test contains a file called foo. The call to dent=readdir(dir) sets dent->d_name to "foo". You already have debugging output that shows this: printf(dent->d_name)¹. Then you try to open foo with fopen, but the file is actually root/test/foo. So this fails every time (unless you happen to also have a file called foo in the current directory).

There are two ways to open the right file:

  • Construct the full name of the file by concatenating the argument to opendir with the file name. Something like:

    /*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*/
    
  • Change into the directory you're listing. For example, change the opendir call to

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

    You have to remember to save the previous directory with getcwd and chdir back to it afterwards. This method is not recommended in production software because it is possible to have a current directory that you can't chdir back into due to permissions.

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


¹ which by the way should be puts(dent->d_name) or even better fputs(dent->d_name, stderr): your original printf call would break if a file name contains %, which is not a big problem for debugging output but is a bad habit to get into.

贵在坚持 2024-09-22 13:18:52

它是 slacker 和 Gilles 两个答案的组合。使用 lstat 但不要像 slacker 所说的那样使用它。您需要向 lstat 发送完整路径,而不仅仅是 dent->d_name。让您知道 lstat 要求您包含 sys/stat.h>
如果您查看 lstat 的手册页,底部会有一个测试程序,或者只看我的。

这是我的程序,试图模仿 Linux 上的“ls”。注意:转义序列颜色在 Windows 中不起作用,以防您担心可移植性。

#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;
}

its a combination of the two answers by slacker and Gilles. use lstat but don't use it like slacker said. You need to send lstat the full path not just dent->d_name. And just so you know lstat requires you include sys/stat.h>
if you look at the man page for lstat there is a test program at the bottom or just look at mine.

Here is my program that tries to mimick "ls" on linux. Note: escape sequence colors doesn't work in windows just in case you were worried about portability.

#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文