Windows上具有通配符的目录中的文件 [英] Files in directory with wildcard on Windows

查看:166
本文介绍了Windows上具有通配符的目录中的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何轻松地从包含通配符的路径中获取所有文件路径?例如: C:/ Data * Set / Files * / *。txt ,我在Linux上使用 glob 函数编写了该代码,但我做不到在Windows上执行此操作:/

how can I easy get all files paths from path containing a wildcards? For example: C:/Data*Set/Files*/*.txt and I wrote it on Linux using glob function but I can't do it on Windows :/

FindFirstFile 不幸的是,目录名称不支持通配符。

FindFirstFile unfortunately doesn't support wildcards in directory names.

我认为应该有Windows解决方案,但找不到。

I think there should be a Windows solution available but I can't find it.

推荐答案

因此,您应该放弃使用特定于操作系统的文件访问权限,而转而使用独立于操作系统的文件:文件系统库

So you should do away with using OS specific file access, in favor of the OS independent: Filesystem Library

假设您获得了 filesystem :: path输入,其中包含通配符。要使用它来解决您的问题,您需要:

Let's say that you're given filesystem::path input which contains the path with wildcards. To use this to solve your problem you'd need to:


  1. 使用 parent_path 分解输入进入目录

  2. 使用 文件名 获取输入文件名

  3. 获取 directory_iterator 或相对输入开始的绝对路径

  4. 创建一个递归函数,该函数以开始 end 迭代器获取的父路径,目录迭代器和文件名

  5. 每当目录或文件名使用'*'使用带有迭代器的 regex 来确定目录前进到下一个

  6. 返回匹配文件的路径或空的 path

  1. Use parent_path to break apart input into directories
  2. Use filename to obtain the input filename
  3. Obtain a directory_iterator to the relative or absolute path where the input begins
  4. Create a recursive function which takes in begin and end iterators to the obtained parent path, the directory iterator, and the filename
  5. Any time a directory or filename uses a '*' use a regex with the iterator to determine the directory which should be progressed to next
  6. Either return the path to the matching file or an empty path

由于很好的Ben Voigt的评论我已经更新了算法以遍历无通配目录。

Due to the excellent Ben Voigt's comment I've updated the algorithm to step over unwildcarded directories.

例如:

regex GenerateRegex(string& arg) {
    for (auto i = arg.find('*'); i != string::npos; i = arg.find('*', i + 2)) {
        arg.insert(i, 1, '.');
    }

    return regex(arg);
}

filesystem::path FindFirstFile(filesystem::path directory, filesystem::path::const_iterator& start, const filesystem::path::const_iterator& finish, string& filename) {
    while (start != finish && start->string().find('*') == string::npos) {
        directory /= *start++;
    }
    filesystem::directory_iterator it(directory);
    filesystem::path result;

    if (it != filesystem::directory_iterator()) {
        if (start == finish) {
            for (auto i = filename.find('.'); i != string::npos; i = filename.find('.', i + 2)) {
                filename.insert(i, 1, '\\');
            }
            const auto re = GenerateRegex(filename);

            do {
                if (!filesystem::is_directory(it->status()) && regex_match(it->path().string(), re)) {
                    result = *it;
                    break;
                }
            } while (++it != filesystem::directory_iterator());
        }
        else {
            const auto re = GenerateRegex(start->string());

            do {
                if (it->is_directory() && regex_match(prev(it->path().end())->string(), re)) {
                    result = FindFirstFile(it->path(), next(start), finish, filename);

                    if (!result.empty()) {
                        break;
                    }
                }
            } while (++it != filesystem::directory_iterator());
        }
    }
    return result;
}

可以通过以下方式调用:

Which can be called with:

const filesystem::path input("C:/Test/Data*Set/Files*/*.txt");

if (input.is_absolute()) {
    const auto relative_parent = input.parent_path().relative_path();

    cout << FindFirstFile(input.root_path(), begin(relative_parent), end(relative_parent), input.filename().string()) << endl;
} else {
    const auto parent = input.parent_path();

    cout << FindFirstFile(filesystem::current_path(), begin(parent), end(parent), input.filename().string()) << endl;
}

实时示例

这篇关于Windows上具有通配符的目录中的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆