【问题标题】:Traversing a Path in c在c中遍历路径
【发布时间】:2014-09-09 01:05:52
【问题描述】:

我正在用 c 语言编写一个程序,它接受一个路径名并遍历该路径,并打印出它遇到的所有文件路径以及该文件的大小(以块为单位),然后如果它是一个 dir,它会打印出 dir 路径名和大小以块为单位。

代码以无限循环结束,并不断提示“无法获取状态:打开的文件过多。”

#include <dirent.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char **argv ){
    struct stat statbuf;
    struct dirent *direntp;
    DIR *dirp;
    if(stat(argv[1], &statbuf) == -1){
        perror("Failed to get file status");
        return 1;
    }
    else if(argc != 2){
        perror("Invalid amount of arguments, showtreesize requires 1 pathname");
        return 1;
    }
    else{
        if(S_ISDIR(statbuf.st_mode) || S_ISREG(statbuf.st_mode)){
            printf("%s      %d", argv[1], depthfirstapply(argv[1],     sizepathfun(argv[1])));
        }
        else{
            if(S_ISCHR(statbuf.st_mode)){
                printf("%s is a character special file.", argv[1]);
            }
            if(S_ISBLK(statbuf.st_mode)){
                printf("%s is a block special file", argv[1]);
            }
            if(S_ISFIFO(statbuf.st_mode)){
                printf("%s is a FIFO special file", argv[1]);
            }
            else{
                printf("%s is not a valid filetype", argv[1]);
            }
        }
        return 0;
    }
}


int sum = 0;
int levelcount = 0;
int isDirectory(char *path){
    struct stat statbuf;
    if(stat(path, &statbuf) == -1)
        return 0;
    else
        return S_ISDIR(statbuf.st_mode);
}

int depthfirstapply(char *path, int pathfun(char *path1)){
    struct dirent *direntp;
    DIR *dirp;
    if(isDirectory(path)){
        printf("%s\n", path);
        if((dirp = opendir(path)) == NULL){
            perror ("Failed to open directory");
            return -1;
        }
        else{
            while((direntp = readdir(dirp)) != NULL) {
                if(isDirectory(direntp->d_name)){
                    int result = depthfirstapply(direntp->d_name, pathfun);
                    if (result > 0){
                        sum += result;
                    }
                }
                else{
                    if(pathfun(direntp->d_name) >= 0){
                        sum += pathfun(direntp->d_name);
                    }
                }
            }
            while ((closedir(dirp) == -1) && (errno == EINTR)) ;
        }
    }
    else{
        sum += pathfun(path);
    }
    return sum;
}



int sizepathfun(char *path){
    struct stat statbuf;
    if(stat(path, &statbuf) == -1){
        perror("Failed to get file status");
        return -1;
    }
    if(S_ISREG(statbuf.st_mode) == 0){
        return -1;
    }
    else{
        printf("%s      %d", path,  statbuf.st_blocks);
        return statbuf.st_blocks;
    }
}

【问题讨论】:

  • 为什么不使用ftw()

标签: c unix path traversal dirent.h


【解决方案1】:

几个问题:

  1. 您需要跳过 ... 条目。否则,您将继续在同一个目录上循环。

  2. isDirectory 中使用lstat() 而不是stat()。否则,您将递归到目录的符号链接,这可能会导致循环。

  3. 当您进入每个目录级别时,您需要将目录组件连接到名称。

  4. depthfirstapply 的第二个参数应该是一个函数。但是在main() 中,你用sizepathfun(argv[1)) 调用它,它返回一个整数。参数应该只是sizepathfun。由于类型不匹配,您应该会收到编译警告。

POSIX 为此提供了一组标准函数fts_XXX()

【讨论】:

  • 非常感谢您的帮助!这些是我根本没有考虑的事情!我进行了前 2 次更改,但仍然遇到相同的错误,只是现在它只出现两次,然后说存在分段错误。关于我可能有什么错误的任何其他想法?
  • 您使用不正确的第二个参数调用 depthfirstapply,请参阅答案中添加的 #4。
  • 非常感谢您的帮助!在修复了这些之后,我终于让它工作了。
猜你喜欢
  • 2019-04-25
  • 1970-01-01
  • 2020-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多