C使用stat获取文件名,大小和权限

时间:2017-03-16 17:05:25

标签: c file subdirectory

我正在尝试以递归方式打印目录及其子目录中的所有文件及其大小和权限。这是代码。

#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递归应该在这里工作并打印子目录中的文件,不仅是名称,还有其他信息(特别是每次都打印正确的绝对路径)。

2 个答案:

答案 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;
    }