从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");