Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C使用stat获取文件名、大小和权限_C_File_Subdirectory - Fatal编程技术网

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

C使用stat获取文件名、大小和权限,c,file,subdirectory,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;

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

#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;
}
#包括
#包括
#包括
#包括
#包括
void listdir(常量字符*名称,整数深度)
{
DIR*DIR;
结构目录*目录读取器;
如果(!(dir=opendir(name)))
返回;
如果(!(dir_reader=readdir(dir)))
返回;
做{
字符路径[1024];
字符绝对路径[1024];
getcwd(绝对路径,1024);
整数大小;
if(dir\u reader->d\u type==DT\u dir){
int len=snprintf(路径,sizeof(路径)-1,“%s/%s”,名称,dir\u reader->d\u name);
路径[len]=0;
if(strcmp(dir_reader->d_name,“.”)==0 | | strcmp(dir_reader->d_name,“…”)==0)
继续;
printf(“%*s[%s]%s\n”,深度*2,”,目录读取器->数据单元名称,路径);
listdir(路径,深度+1);
}
否则{
结构统计;
char*tmp_path=path+1;
strcat(绝对路径、tmp路径);
if(stat(dir\u reader->d\u name,&st)==0){
尺寸=标准尺寸;
}
printf(“%*s-%s%s%d”,深度*2,”,dir\u reader->d\u名称,绝对路径,大小);
printf((st.st\U模式和S\U IRUSR)?“r”:“—”;
printf((st.st\U模式和S\U IWUSR)?“w”:“-”);
printf((st.st_模式和S_IXUSR)?“x”:“-”);
printf((st.st\U模式和S\U IRGRP)?“r”:“—”;
printf((st.st\U模式和S\U IWGRP)-“w”:“-”;
printf((st.st_模式和S_IXGRP)?“x”:“-”;
printf((圣圣圣日耳曼模式和圣日耳曼模式)-“r”:“—”;
printf((st.st_模式和S_IWOTH)-“w”:“-”;
printf((st.st_模式和S_IXOTH)?“x”:“-”号;
printf(“\n”);
}
}而(dir_reader=readdir(dir));
closedir(dir);
}
内部主(空){
listdir(“.”,0);
返回0;
}

不幸的是,输出仅为主目录中的文件生成大小和权限,对于子目录中的文件,它仅打印为0作为大小,而----------作为权限。我看不出发生这种情况的原因,IMO递归应该在这里工作,并且打印子目录中的文件,不仅是名称,还有其他信息(特别是每次都打印正确的绝对路径)。

之所以大小为0,是因为您没有看到正确的文件。在子目录中,您将“myfile.txt”传递给
stat
而不是“mysubdir/myfile.txt”,因此除非当前目录中碰巧有另一个“myfile.txt”,否则它将无法工作


解决办法很简单。您需要有一个新字符串,将完整路径和文件名连接在一起,并将其传递到文件检查的
部分顶部的
stat

    char* tmp_path = path + 1;
    strcat(absolute_path,tmp_path);
尚未设置
路径
变量。因此,您正在读取未初始化的数据,调用未定义的行为。调用
stat
时也没有检查错误,因此您不知道它失败了

您需要将
path
的设置移动到
if
块的外部,以便在这两种情况下都发生。您还需要将
absolute\u path
传递到
stat
而不是
dir\u reader->d\u 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;
    }

注意:不需要在
snprintf(path,sizeof(path)-1中使用-1…
也不需要
path[len]=0;
。根据负值检查
len
,或者
len>=sizeof(path)
就可以了
strcat(绝对路径,tmp_路径);
?如果
stat(
stat
失败。您以错误的方式管理绝对路径;在递归的每一个深度,您都会使用getcwd(),因为您不更改“当前目录”。可能最好使用与例程第一部分相同的方法-始终使用收到的参数snprintf()并以增量方式构造新的(相对)路径。