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

发布于 2024-07-24 18:41:08 字数 223 浏览 4 评论 0原文

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

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

撩人痒 2024-07-31 18:41:08

请参阅 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);
}

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

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


为了更好地控制遍历,还有 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;
}

再说一次,它既没有经过编译测试,也没有经过运行测试,但我想我会提到它。

See man ftw for a simple "file tree walk". I also used fnmatch in this example.

#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.


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.

#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.

错爱 2024-07-31 18:41:08

Boost.Filesystem 允许您做到这一点。 查看文档

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

Boost.Filesystem allows you to do that. 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. This page shows many examples on how to do just that.

梦幻的心爱 2024-07-31 18:41:08

我是老派,没有 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;
}

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.

#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;
}
别把无礼当个性 2024-07-31 18:41:08

您还可以使用 glob/globfree。

You can also use glob/globfree.

蝶…霜飞 2024-07-31 18:41:08

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

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.

又怨 2024-07-31 18:41:08

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

You will want to use the directory functions declared in dirent.h. This wikipedia page describes 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文