C ++中的递归文件夹扫描

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/983376/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:14:39  来源:igfitidea点击:

recursive folder scanning in c++

c++linuxdirectoryembedded

提问by Stulli

I want to scan a directory tree and list all files and folders inside each directory. I created a program that downloads images from a webcamera and saves them locally. This program creates a filetree based on the time the picture is downloaded. I now want to scan these folders and upload the images to a webserver but I′m not sure how I can scan the directories to find the images. If anyone could post some sample code it would be very helpful.

我想扫描目录树并列出每个目录中的所有文件和文件夹。我创建了一个从网络摄像头下载图像并将它们保存在本地的程序。该程序根据图片下载的时间创建一个文件树。我现在想扫描这些文件夹并将图像上传到网络服务器,但我不确定如何扫描目录以找到图像。如果有人可以发布一些示例代码,那将非常有帮助。

edit: I′m running this on an embedded linux system and don′t want to use boost

编辑:我在嵌入式 linux 系统上运行它,不想使用 boost

回答by ephemient

See man ftwfor a simple "file tree walk". I also used fnmatchin this example.

有关man ftw简单的“文件树遍历”,请参阅。我也在fnmatch这个例子中使用过。

#include <ftw.h>
#include <fnmatch.h>

static const char *filters[] = {
    "*.jpg", "*.jpeg", "*.gif", "*.png"
};

static int callback(const char *fpath, const struct stat *sb, int typeflag) {
    /* if it's a file */
    if (typeflag == FTW_F) {
        int i;
        /* for each filter, */
        for (i = 0; i < sizeof(filters) / sizeof(filters[0]); i++) {
            /* if the filename matches the filter, */
            if (fnmatch(filters[i], fpath, FNM_CASEFOLD) == 0) {
                /* do something */
                printf("found image: %s\n", fpath);
                break;
            }
        }
    }

    /* tell ftw to continue */
    return 0;
}

int main() {
    ftw(".", callback, 16);
}

(Not even compile-tested, but you get the idea.)

(甚至没有经过编译测试,但你明白了。)

This is much simpler than dealing with DIRENTs and recursive traversal yourself.

这比DIRENT自己处理s 和递归遍历要简单得多。



For greater control over traversal, there's also fts. In this example, dot-files (files and directories with names starting with ".") are skipped, unless explicitly passed to the program as a starting point.

为了更好地控制遍历,还有fts. 在此示例中,将跳过点文件(名称以“.”开头的文件和目录),除非明确将其作为起点传递给程序。

#include <fts.h>
#include <string.h>

int main(int argc, char **argv) {
    char *dot[] = {".", 0};
    char **paths = argc > 1 ? argv + 1 : dot;

    FTS *tree = fts_open(paths, FTS_NOCHDIR, 0);
    if (!tree) {
        perror("fts_open");
        return 1;
    }

    FTSENT *node;
    while ((node = fts_read(tree))) {
        if (node->fts_level > 0 && node->fts_name[0] == '.')
            fts_set(tree, node, FTS_SKIP);
        else if (node->fts_info & FTS_F) {
            printf("got file named %s at depth %d, "
                "accessible via %s from the current directory "
                "or via %s from the original starting directory\n",
                node->fts_name, node->fts_level,
                node->fts_accpath, node->fts_path);
            /* if fts_open is not given FTS_NOCHDIR,
             * fts may change the program's current working directory */
        }
    }
    if (errno) {
        perror("fts_read");
        return 1;
    }

    if (fts_close(tree)) {
        perror("fts_close");
        return 1;
    }

    return 0;
}

Again, it's neither compile-tested nor run-tested, but I thought I'd mention it.

同样,它既没有经过编译测试也没有经过运行测试,但我想我会提到它。

回答by Martin Cote

Boost.Filesystem allows you to do that. Check out the docs!

Boost.Filesystem 允许你这样做。查看文档

EDIT:
If you are using Linux and you don't want to use Boost, you will have to use the Linux native C functions. This pageshows many examples on how to do just that.

编辑:
如果您使用的是 Linux 并且不想使用 Boost,则必须使用 Linux 本机 C 函数。 此页面显示了许多有关如何做到这一点的示例。

回答by Martin Cote

I'm old school, no ftw() for me! This is crude (it's been a while since I did straight C programming), and lots of stuff is hardcoded, and I probably messed up my length calculations for the strnc*() functions, but you get the idea. There's a similar example in K&R btw.

我是老派,对我来说没有 ftw() !这很粗糙(自从我直接进行 C 编程以来已经有一段时间了),而且很多东西都是硬编码的,我可能搞砸了 strnc*() 函数的长度计算,但你明白了。顺便说一句,K&R 中有一个类似的例子。

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

#include <sys/types.h>
#include <dirent.h>

void listdir(char* dirname, int lvl);

int main(int argc, char** argv)
{

  if (argc != 2) {
    fprintf(stderr, "Incorrect usage!\n");
    exit(-1);
  }
  listdir(argv[1], 0);


  return 0;
}

void listdir(char* dirname, int lvl)
{

  int i;
  DIR* d_fh;
  struct dirent* entry;
  char longest_name[4096];

  while( (d_fh = opendir(dirname)) == NULL) {
    fprintf(stderr, "Couldn't open directory: %s\n", dirname);
    exit(-1);
  }

  while((entry=readdir(d_fh)) != NULL) {

    /* Don't descend up the tree or include the current directory */
    if(strncmp(entry->d_name, "..", 2) != 0 &&
       strncmp(entry->d_name, ".", 1) != 0) {

      /* If it's a directory print it's name and recurse into it */
      if (entry->d_type == DT_DIR) {
        for(i=0; i < 2*lvl; i++) {
          printf(" ");
        }
        printf("%s (d)\n", entry->d_name);

        /* Prepend the current directory and recurse */
        strncpy(longest_name, dirname, 4095);
        strncat(longest_name, "/", 4095);
        strncat(longest_name, entry->d_name, 4095);
        listdir(longest_name, lvl+1);
      }
      else {

        /* Print some leading space depending on the directory level */
        for(i=0; i < 2*lvl; i++) {
          printf(" ");
        }
        printf("%s\n", entry->d_name);
      }
    }
  }

  closedir(d_fh);

  return;
}

回答by Martin Cote

You will want to use the directory functions declared in dirent.h. This wikipedia pagedescribes them and includes sample code. For your application, once you have identified a directory, you will want to call the processing function again recursively to process the directory contents.

您将需要使用在 dirent.h 中声明的目录函数。这个维基百科页面描述了它们并包括示例代码。对于您的应用程序,一旦您确定了目录,您将需要再次递归调用处理函数来处理目录内容。

回答by Joe

You can also use glob/globfree.

您也可以使用 glob/globfree。

回答by Denis C

I think if you can use Qt/Embedded, there are QDir and QFileInfo classes which can help you, though it depends if you can use the Qt. The question is which API your system provides.

我认为如果您可以使用 Qt/Embedded,则有 QDir 和 QFileInfo 类可以帮助您,尽管这取决于您是否可以使用 Qt。问题是您的系统提供了哪个 API。