从C列出Linux中的目录

时间:2010-04-09 13:47:31

标签: c linux

我正在尝试使用来自c的linux api来模拟linux命令ls。查看代码它确实有意义,但是当我运行它时,我得到“stat error:没有这样的文件或目录”。我检查过opendir工作正常。我认为问题在于stat,即使我认为它应该返回0,它仍返回-1。

我错过了什么?

感谢您的帮助。

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

int main(int argc, char *argv[])
{
 DIR *dirp;
 struct dirent *direntp;
 struct stat stat_buf;
 char *str;

 if (argc != 2)
 {
  fprintf( stderr, "Usage: %s dir_name\n", argv[0]);
  exit(1);
 }

 if ((dirp = opendir( argv[1])) == NULL)
 {
  perror(argv[1]);
  exit(2);
 }

 while ((direntp = readdir( dirp)) != NULL)
 {
  if (stat(direntp->d_name, &stat_buf)==-1)
  {
   perror("stat ERROR");
   exit(3);
  }
  if (S_ISREG(stat_buf.st_mode)) str = "regular";
  else if (S_ISDIR(stat_buf.st_mode)) str = "directory";
  else str = "other";
  printf("%-25s - %s\n", direntp->d_name, str);
 }

 closedir(dirp);
 exit(0);
}

5 个答案:

答案 0 :(得分:3)

这是因为您没有说明实际文件。它在不同的目录中。如果您想要真实的文件名,请将argv[1]direntp->d_name合并为一个'/'。

另外,匈牙利语的命名很蹩脚,即使是最后的“p”这个小小的一点。如果你有这么多变量,你需要在他们的名字中跟踪他们的类型,你做错了。

以下是您的计划的修订版本:

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>
#include <limits.h>
#include <sys/param.h>

int main(int argc, char *argv[])
{
 DIR *dirp;
 struct dirent *direntp;
 struct stat stat_buf;
 char *str;
 char fullpath[MAXPATHLEN + 1];
 size_t dirnamelen;

 if (argc != 2)
 {
  fprintf( stderr, "Usage: %s dir_name\n", argv[0]);
  exit(1);
 }
 strncpy(fullpath, argv[1], MAXPATHLEN - 1); /* account for trailing '/' */
 fullpath[MAXPATHLEN - 1] = '\0';
 dirnamelen = strlen(fullpath);
 if (strlen(argv[1]) > dirnamelen) {
  fprintf( stderr, "Directory name is too long: %s", argv[1] );
  exit(2);
 }

 fullpath[dirnamelen++] = '/';
 fullpath[dirnamelen] = '\0';

 if ((dirp = opendir( argv[1])) == NULL)
 {
  perror(argv[1]);
  exit(2);
 }

 while ((direntp = readdir( dirp)) != NULL)
 {
  fullpath[dirnamelen] = '\0';
  if ((dirnamelen + strlen(direntp->d_name)) > MAXPATHLEN) {
   fprintf(stderr, "File %s + directory %s is too long.", direntp->d_name, fullpath);
   continue;
  } else {
   /* strncpy is mild overkill because the if statement has verified that
      there's enough space.  */
   strncpy(fullpath + dirnamelen, direntp->d_name, MAXPATHLEN - dirnamelen);
   fullpath[MAXPATHLEN] = '\0';
  }
  if (stat(fullpath, &stat_buf)==-1)
  {
   perror("stat ERROR");
   exit(3);
  }
  if (S_ISREG(stat_buf.st_mode)) str = "regular";
  else if (S_ISDIR(stat_buf.st_mode)) str = "directory";
  else str = "other";
  printf("%-25s - %s\n", direntp->d_name, str);
 }

 closedir(dirp);
 exit(0);
}

请注意,我使用MAXPATHLEN(来自<limits.h>)并仔细检查以确保没有任何缓冲区溢出。您应该在代码中执行相同的操作。

修改:更改了代码以使用strn系列函数以增加安全性。

答案 1 :(得分:2)

添加

#include <unistd.h>
...
chdir(argv[1]);

或使用如此

的完整路径名调用stat
...
char fullpath[MAXPATHLEN];
snprintf(fullpath, sizeof(fullpath), "%s/%s", argv[1], direntp->d_name);
if (stat(fullpath, &stat_buf) == -1)
...

答案 2 :(得分:1)

为什么不尝试这个?只需像argv[1]

那样提供/home/sabri/Desktop/Test的路径
int main(int argc, char *argv[]) 
{
    struct dirent *direntp;
    DIR *dirp;

    if (argc != 2) 
    {
       fprintf(stderr, "Usage: %s directory_name\n", argv[0]);
       return 1;
    }

if ((dirp = opendir(argv[1])) == NULL) 
{
    perror ("Failed to open directory");
    return 1;
}

while ((direntp = readdir(dirp)) != NULL)
    printf("%s\n", direntp->d_name);

while ((closedir(dirp) == -1) && (errno == EINTR)) ;

return 0;

}

答案 3 :(得分:0)

其他人建议为stat()建立完整路径,或使用chdir()。这两个都可以工作(虽然它们受到竞争条件的影响,如果目录在你正在阅读时被重命名)。

另一种不受竞争条件限制的替代方案是使用fstatat(),因此可以说更“正确”。只需将您现有的stat()电话替换为:

即可
fstatat(dirfd(dirp), direntp->d_name, &stat_buf, 0)

chdir()方法也可以无竞争条件:使用fchdir(dirfd(dirp))代替chdir(),或者将目录更改为argv[1]然后打开"."opendir()。路径名构造方法不能无竞争条件。)

答案 4 :(得分:-2)

如果您在unix上使用,则可以使用系统命令。

system("ls -ltr | grep -d");