从C列出Linux中的目录

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

我错过了什么?

谢谢你的帮助。

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

这是因为你没有说明实际的文件。 它在不同的目录中。 如果你想要真正的文件名,请将argv[1]direntp->d_name与它们之间的’/’组合在一起。

此外,匈牙利语命名是icky,即使是最后一点像’p’的小点。 如果你有这么多变量,你需要在他们的名字中跟踪他们的类型你做错了什么。

这是您的程序的修订版本:

 #include  #include  #include  #include  #include  #include  #include  #include  #include  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 (来自 )并仔细检查以确保没有任何缓冲区溢出。 您应该在代码中执行相同的操作。

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

 #include  ... chdir(argv[1]); 

或使用像这样的完整路径名调用stat

 ... char fullpath[MAXPATHLEN]; snprintf(fullpath, sizeof(fullpath), "%s/%s", argv[1], direntp->d_name); if (stat(fullpath, &stat_buf) == -1) ... 

为什么不尝试这个? 只需像这样/home/sabri/Desktop/Test给出argv[1]的路径

 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; 

}

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

另一种不受竞争条件影响的替代方案是使用fstatat() ,因此可以说更“正确”。 只需用以下内容替换现有的stat()调用:

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

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

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

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