使用C语言中的Glob()函数列出目录中的文件。

3

基本上,到目前为止我有这段代码:

#include <glob.h>
#include <string.h>
#include <stdio.h>

# define ERROR 1
# define FAILURE -1

int main(int ac, char **av)
{
  glob_t globlist;
  int i;

  i = 0;               
  if (ac == 1)
    return (-1);
  else
    {
      if (glob(av[1], GLOB_PERIOD, NULL, &globlist) == GLOB_NOSPACE
          || glob(av[1], GLOB_PERIOD, NULL, &globlist) == GLOB_NOMATCH)
        return (FAILURE);
      if (glob(av[1], GLOB_PERIOD, NULL, &globlist) == GLOB_ABORTED)
        return (ERROR);
      while (globlist.gl_pathv[i])
        {
          printf("%s\n", globlist.gl_pathv[i]);
          i++;
        }
    }
  return (0);
}

当我输入例如./a.out "*"时,它会打印我所在的所有文件和目录,但不会打印目录中的内容。我应该如何做才能打印包括子文件/文件夹在内的所有文件?
谢谢

1
与您的问题完全无关,但是您不应该从main函数返回-1。在“成功”时返回0,在“失败”时返回小于256的值。这是因为在POSIX系统(包括Linux、OSX和所有现代Unix系统)中,高位具有特殊含义。 - Some programmer dude
你可能想看一下在 dirent.h 中原型化的函数。 - alk
@alk 我知道dirent.h,但我不太清楚如何很好地使用它。就像我认为我必须进行递归,我错了吗? - iNukeLaPeste
是的,你需要使用递归。因此,你应该将你的glob代码放入一个函数中(而不是在main()中)。同时,我同意有关使用return()的建议。祝你好运。 - shellter
@shellter 谢谢!基本上我先进行一次全局匹配,然后访问所有目录,再进行一次全局匹配? - iNukeLaPeste
显示剩余3条评论
1个回答

7
如果您想检查整个目录树,而不是一个特定的路径和文件名模式,请使用nftw()代替glob()。使用opendir()/readdir()/closedir()重新发明轮子是绝对愚蠢的,特别是因为nftw()应该优雅地处理文件系统更改,而自己编写的遍历树代码通常忽略所有艰难的问题,并且仅在自己的机器上的最佳条件下工作,在其他地方则以壮观而奇妙的方式失败。
在过滤函数中,使用fnmatch()使用glob模式决定文件名是否可接受。
如果您希望改用正则表达式进行过滤,请在调用nftw()之前使用regcomp()编译模式,然后在过滤函数中使用regexec()。(正则表达式比glob模式更强大,它们被编译成紧凑的状态机,因此它们也非常高效。)
如果您不确定区别,请参阅维基百科上有关glob模式正则表达式的文章,这些文章非常有用和信息丰富。
所有上述内容都在POSIX.1-2008中定义,因此它们可在所有POSIX操作系统上移植。

非常感谢您提供的所有信息。不幸的是,我无法使用nftw函数,因为这是一个学校项目,该函数未经授权。 - iNukeLaPeste
在这种情况下,也许你应该考虑循环遍历所有命令行参数,而不仅仅使用第一个参数av[1]?这样你就可以提供多个通配符模式,例如 '*' '*/*' '*/*/*',以查看最多三级目录的文件。递归扫描目录很容易出错,而且真的,应该小心谨慎地完成。 - Nominal Animal
我的一个最喜欢的绊脚石是在另一个窗口中运行 new="dirname"; i=1; while true; do old="$new"; new="dirname$i"; i=$[i+1]; mv "$old" "$new" ; done,在你递归检查的树中。它将一个最初名为 dirname 的目录重命名为 dirname1,每次数字都会增加,尽可能多地进行压力测试。一个正确编写的树递归不会介意,尽管它可能会错过以该更改名称目录开头的子树。糟糕的实现将会混淆并重复执行某些操作,或者崩溃。 - Nominal Animal
1
即使是更恶劣的压力测试也很容易构建。特别是,在同一目录中重命名是文件系统上的“轻量级”操作,但在目录之间移动则需要更多的工作——并且更容易混淆或崩溃糟糕的树形扫描器。你可能认为这是过度的或罕见的,但实际上并不是!例如,日志文件被“轮换”,这通常包括三个重命名(或移动)的三元组。在emacs/vi/nano/gedit等编辑文件时也是如此。或者你可能在程序工作时使用桌面环境移动文件夹。这样的事情确实会发生。 - Nominal Animal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接