我正在尝试以递归方式打印目录及其子目录中的所有文件及其大小和权限。这是代码。
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <sys/stat.h>
void listdir(const char *name, int depth)
{
DIR *dir;
struct dirent *dir_reader;
if (!(dir = opendir(name)))
return;
if (!(dir_reader = readdir(dir)))
return;
do {
char path[1024];
char absolute_path[1024];
getcwd(absolute_path, 1024);
int size;
if (dir_reader->d_type == DT_DIR) {
int len = snprintf(path, sizeof(path)-1, "%s/%s", name, dir_reader->d_name);
path[len] = 0;
if (strcmp(dir_reader->d_name, ".") == 0 || strcmp(dir_reader->d_name, "..") == 0)
continue;
printf("%*s[%s] %s\n", depth*2, "", dir_reader->d_name,path);
listdir(path, depth + 1);
}
else{
struct stat st;
char* tmp_path = path + 1;
strcat(absolute_path,tmp_path);
if (stat(dir_reader->d_name, &st) == 0){
size = st.st_size;
}
printf("%*s- %s %s %d ", depth*2, "", dir_reader->d_name, absolute_path, size);
printf( (st.st_mode & S_IRUSR) ? "r" : "-");
printf( (st.st_mode & S_IWUSR) ? "w" : "-");
printf( (st.st_mode & S_IXUSR) ? "x" : "-");
printf( (st.st_mode & S_IRGRP) ? "r" : "-");
printf( (st.st_mode & S_IWGRP) ? "w" : "-");
printf( (st.st_mode & S_IXGRP) ? "x" : "-");
printf( (st.st_mode & S_IROTH) ? "r" : "-");
printf( (st.st_mode & S_IWOTH) ? "w" : "-");
printf( (st.st_mode & S_IXOTH) ? "x" : "-");
printf("\n");
}
} while (dir_reader = readdir(dir));
closedir(dir);
}
int main(void) {
listdir(".", 0);
return 0;
}
不幸的是,输出只对主目录中的文件产生大小和权限,对于子目录中的文件,它只打印0作为大小和---------作为权限。我没有看到它发生的原因,IMO递归应该在这里工作并打印子目录中的文件,不仅是名称,还有其他信息(特别是每次都打印正确的绝对路径)。
答案 0 :(得分:0)
您获得0大小的原因是因为您没有查看正确的文件。在子目录中,您传递了#34; myfile.txt&#34; to stat
not&#34; mysubdir / myfile.txt&#34;所以除非碰巧有另一个&#34; myfile.txt&#34;在当前目录中,它不会工作。
解决方案很简单。您需要一个新的字符串,将完整路径和文件名连接在一起,并将其传递给stat
。
答案 1 :(得分:0)
在文件else
部分的顶部,检查:
char* tmp_path = path + 1;
strcat(absolute_path,tmp_path);
尚未设置path
变量。因此,您正在读取未初始化的数据,从而调用未定义的行为。当您致电stat
时,您也没有检查错误,因此您不知道它失败了。
您需要在path
块之外移动if
的设置,以便在两种情况下均可。您还需要将absolute_path
传递给stat
,而不是dir_reader->d_name
,这只是文件名。
// do this outsize of the if
int len = snprintf(path, sizeof(path)-1, "%s/%s", name, dir_reader->d_name);
path[len] = 0;
if (dir_reader->d_type == DT_DIR) {
if (strcmp(dir_reader->d_name, ".") == 0 || strcmp(dir_reader->d_name, "..") == 0)
continue;
printf("%*s[%s] %s\n", depth*2, "", dir_reader->d_name,path);
listdir(path, depth + 1);
}
else{
struct stat st;
char* tmp_path = path + 1;
strcat(absolute_path,tmp_path);
// use absolute_path to get the file status
if (stat(absolute_path, &st) == 0){
size = st.st_size;
} else {
// error, print message
perror("stat failed");
continue;
}