简体   繁体   English

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

[英]recursive folder scanning in c++

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. 我现在想扫描这些文件夹并将图像上传到Web服务器,但是我不确定如何扫描目录以查找图像。 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

See man ftw for a simple "file tree walk". 有关简单的“文件树遍历”,请参见man ftw I also used fnmatch in this example. 在此示例中,我还使用了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 DIRENT s and recursive traversal yourself. 这比自己处理DIRENT和递归遍历要简单得多。


For greater control over traversal, there's also fts . 为了更好地控制遍历,还可以使用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. 在此示例中,点文件(名称以“。”开头的文件和目录)将被跳过,除非作为起点明确传递给程序。

#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. 同样,它既没有经过编译测试也没有运行测试,但我想我已经提到了。

Boost.Filesystem allows you to do that. Boost.Filesystem允许您执行此操作。 Check out the docs ! 查看文档

EDIT: 编辑:
If you are using Linux and you don't want to use Boost, you will have to use the Linux native C functions. 如果您使用的是Linux,并且不想使用Boost,则必须使用Linux本机C函数。 This page shows many examples on how to do just that. 此页面显示了有关如何执行此操作的许多示例。

I'm old school, no ftw() for me! 我是老学校,对我没有ftw()! 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. 这很粗糙(自从我进行直接C编程以来已经有一段时间了),并且很多东西都是硬编码的,而且我可能弄乱了strnc *()函数的长度计算,但是您明白了。 There's a similar example in K&R btw. K&R btw中有一个类似的例子。

#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;
}

You will want to use the directory functions declared in dirent.h. 您将要使用dirent.h中声明的目录功能。 This wikipedia page describes them and includes sample code. Wikipedia页面描述了它们并包括示例代码。 For your application, once you have identified a directory, you will want to call the processing function again recursively to process the directory contents. 对于您的应用程序,一旦确定了目录,您将希望再次递归调用处理函数以处理目录内容。

您也可以使用glob / globfree。

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. 我认为,如果可以使用Qt / Embedded,则有QDir和QFileInfo类可以为您提供帮助,尽管这取决于您是否可以使用Qt。 The question is which API your system provides. 问题是您的系统提供哪种API。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM