【问题标题】:Program to print directories using c not working, issues with recursive call使用 c 打印目录的程序不起作用,递归调用问题
【发布时间】:2017-05-07 12:23:46
【问题描述】:

我需要创建一个基本上类似于 Linux 上的列表实用程序的程序。我一直在努力让它发挥作用,我已经很接近了,但现在我被卡住了。本质上,它将打印目录中包含的任何文件和子目录(即,如果我运行 ./project3,它会列出该目录中的任何内容)。但是,一旦我尝试让递归调用正常工作,它就会吐出如下内容:

sh: 1: /home/RageKage/Documents/Project3/dir1: Permission denied

这就是我卡住的地方,我不确定从这里该怎么做。我正在获取目录的路径以使用 realpath 进行探索,并且效果很好,但是递归调用不起作用,我不确定自己做错了什么。任何帮助将不胜感激,因为我对此比较陌生。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <limits.h>

int main (int argc, char *argv[])
{
    DIR *dir;
    struct dirent *sd;
    const char *direct;
    char buf[PATH_MAX + 1];

    if (argc < 2)
    {
        direct = ".";
    }else{
        direct = argv[1];
        //printf("Hey this is argv[1]:  %s\n", argv[1]);
    }


    dir = opendir(direct);

    if (dir == NULL)
    {
        printf("ERROR! NO DIRECTORY TO OPEN!\n");
        exit(1);
    }

    while( (sd=readdir(dir)) != NULL )
    {

        if (!strcmp(sd->d_name, ".") || !strcmp(sd->d_name, ".."))
        {

        }else{
            printf("\n>> %s\n", sd->d_name);
        }


        if (!strcmp(sd->d_name, "..") ||  !strcmp(sd->d_name, "."))
        {

        }else if (sd->d_type == 4){
            printf("Attempting to Run!\n");

            realpath(sd->d_name, buf);
            printf("[%s]\n", buf);

            system(("./project3 %s", buf));
            printf("\n");

        }

    }


    closedir(dir);

    return 0;
}

【问题讨论】:

  • 递归在哪里?
  • realpath(sd-&gt;d_name, buf); system(buf); buf 包含目录的真实路径加上我相信用于启动程序的命令,所以类似于 ./project3 /home/RageKageDocuments/Project3/dir3。至少这是我打印 buf 时得到的结果。
  • 真的吗?当你运行这个程序时,你得到的确切输出是什么?
  • 我不知道如何发布输出,所以如果有帮助,我就截屏了link
  • 这并没有说明./project3buf 中。

标签: c linux shell directory-structure ls


【解决方案1】:
system(("./project3 %s", buf));

您是否再次递归调用程序本身?这听起来有点低效,而且很难做到,因为您需要知道可执行文件在哪里。一般来说,它可能在任何地方(以/bin/usr/bin 等开头),而您在argv[0] 中可能得到的只是文件名部分,而不是整个路径。

另外,正如 cmets 中所说,func((this, that))func(that) 相同,而不是 func(this, that),因为括号使逗号充当逗号运算符,而不是作为参数分隔符。而system() 无论如何只接受一个参数,因此您需要使用sprintf() 来构建命令行。 (或者也许使用exec() 函数来实际给出单独的参数而不调用shell,但是你也需要使用fork()。)

我建议放弃这个想法,将目录树放入它自己的函数中,然后递归调用它:

void walkpath(void)
{
    DIR *dir = opendir(".");
    struct dirent *sd;
    while((sd = readdir(dir)) != NULL) {
        /* ... */
        if (sd->d_type == DT_DIR) {
            chdir(sd->d_name);
            walkpath();
            chdir("..");
        }
    }
}
int main(...)
{
     /* ... */
     chdir(directory);
     walkpath();
}

我在这里使用chdir 来更改进程的工作目录以及walk。如果您需要跟踪完整的目录名称,那么您需要添加它。

另外,现在您对... 进行了两次测试。使用continue 来结束循环的迭代,这样您就不需要再次测试相同的东西了。

if (strcmp(sd->d_name, ".") == 0 || strcmp(sd->d_name, "..") == 0) {
    continue;
}

【讨论】:

  • 这帮助了很多!再次递归调用该程序会导致大量问题,因此我按照您的建议进行了操作并将程序拆分。我写的和你发的不一样,但最终结果是一样的。非常感谢!
猜你喜欢
  • 2018-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-12
  • 1970-01-01
  • 1970-01-01
  • 2021-12-25
  • 1970-01-01
相关资源
最近更新 更多