Windows上具有通配符的目录中的文件 [英] Files in directory with wildcard on 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:
- 使用
parent_path
分解输入
进入目录 - 使用
文件名
获取输入
文件名 - 获取
directory_iterator
或相对输入
开始的绝对路径 - 创建一个递归函数,该函数以
开始
和end
迭代器获取的父路径,目录迭代器和文件名 - 每当目录或文件名使用
'*'
使用带有迭代器的regex
来确定目录前进到下一个 - 返回匹配文件的路径或空的
path
- Use
parent_path
to break apartinput
into directories - Use
filename
to obtain theinput
filename - Obtain a
directory_iterator
to the relative or absolute path where theinput
begins - Create a recursive function which takes in
begin
andend
iterators to the obtained parent path, the directory iterator, and the filename - Any time a directory or filename uses a
'*'
use aregex
with the iterator to determine the directory which should be progressed to next - 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屋!