有没有一种方法可以在C语言中列出给定目录路径中的所有子目录?我希望能够使用
stat()
函数来实现,但它只适用于文件。stat()
函数来实现,但它只适用于文件。stat 命令也适用于目录。
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
int num_dirs(const char* path)
{
int dir_count = 0;
struct dirent* dent;
DIR* srcdir = opendir(path);
if (srcdir == NULL)
{
perror("opendir");
return -1;
}
while((dent = readdir(srcdir)) != NULL)
{
struct stat st;
if(strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
continue;
if (fstatat(dirfd(srcdir), dent->d_name, &st, 0) < 0)
{
perror(dent->d_name);
continue;
}
if (S_ISDIR(st.st_mode)) dir_count++;
}
closedir(srcdir);
return dir_count;
}
fstatat
替换了 stat
(这意味着你不必操心创建完整路径,并且避免了竞争条件),并处理了 opendir
和 fstatat
的错误(在实践中很有可能出现,比如“权限被拒绝”之类的问题)。 - caf/*
I had need in something like this not so long ago (my difference is I
needed recursive scan) so I added only some comments... Sorry for recursion
but I was short of time and this was only part of internal one-time tool.
*/
/* Print all the dirs starting from <path> [maybe recursive]. */
int print_dirs(const char *path, int recursive)
{
struct dirent *direntp = NULL;
DIR *dirp = NULL;
size_t path_len;
/* Check input parameters. */
if (!path)
return -1;
path_len = strlen(path);
if (!path || !path_len || (path_len > _POSIX_PATH_MAX))
return -1;
/* Open directory */
dirp = opendir(path);
if (dirp == NULL)
return -1;
while ((direntp = readdir(dirp)) != NULL)
{
/* For every directory entry... */
struct stat fstat;
char full_name[_POSIX_PATH_MAX + 1];
/* Calculate full name, check we are in file length limts */
if ((path_len + strlen(direntp->d_name) + 1) > _POSIX_PATH_MAX)
continue;
strcpy(full_name, path);
if (full_name[path_len - 1] != '/')
strcat(full_name, "/");
strcat(full_name, direntp->d_name);
/* Ignore special directories. */
if ((strcmp(direntp->d_name, ".") == 0) ||
(strcmp(direntp->d_name, "..") == 0))
continue;
/* Print only if it is really directory. */
if (stat(full_name, &fstat) < 0)
continue;
if (S_ISDIR(fstat.st_mode))
{
printf("%s\n", full_name);
if (recursive)
print_dirs(full_name, 1);
}
}
/* Finalize resources. */
(void)closedir(dirp);
return 0;
}
/* We are taking first argument as initial path name. */
int main(int argc, const char* argv[])
{
if (argc < 2)
return -1;
print_dirs(argv[1], 1);
return 0;
}
正如其他人所指出的,stat(2)
可以在所有类型的文件和设备上正常工作。它会读取到远端文件的符号链接;如果您需要有关符号链接本身的信息,请使用 lstat(2)
。
要列出单个目录中所有目录的名称(非递归),请使用 readdir(3)
函数系列的组合。
要递归列出所有目录的名称,请使用 ftw(3)
或 nftw(3)
函数进行“文件树遍历”(从而得到它们的名称;'n' 代表 'new')。
stat()
应该至少能够告诉我们它是一个类 UNIX 的操作系统。 - Joeystat()
函数可以用于文件,但是目录条目也是文件。因此,stat("/etc/passwd", &buf)
和stat("/etc/", &buf)
都可以使用。 - Sean Bright