I am new to C and I am struggling a bit doing basic things. I am sorry if this question is too stupid or it has been asked somewhere. I tried to search on StackOverflow without success.
I have the following problem: I have two folders with the same number of files, let's call this number N. I would like to do a for loop like the following:
for file1 in directory 1 , file2 in directory2:
filename_file_folder_1 = get_filename(file1);
filename_file_folder_2 = get_filename(file2);
It must be possible since I would know how to do it probably in Python. Therefore, I expect also C to allow this. However, I could not find a solution to this problem yet.
CodePudding user response:
#include <filesystem>
using std::filesystem::path;
using std::filesystem::directory_iterator;
template<typename F>
void for_each_pair_of_files_in(path dir_a, path dir_b, F f)
{
using Iter = directory_iterator;
auto it_a = Iter{dir_a};
auto it_b = Iter{dir_b};
for (; it_a != Iter{} && it_b != Iter{}; it_a, it_b)
f(*it_a, *it_b);
}
void some_compare(path dir_a, path dir_b);
void do_it()
{
for_each_pair_of_files_in("a/b", "b/c", [](path a, path b) {
some_compare(a, b);
});
}
https://godbolt.org/z/rq8GEMsrd
Disclaimer: I don't know what are you doing exactly, also there is no any warranty that both iterators will have some specific order, so probably some element matching is needed.
In C 20, there is std::ranges::views::zip, which is equivalent to Python's zip, but from what I've tried there is no compiler which has this feature yet.
CodePudding user response:
I hope this is what you're looking for: (assuming directory1/2 are vectors/arrays)
for (int i = 0 ; i < N; i ) {
file1 = directory1[i];
file2 = directory2[i];
// can use file1 and file2 however you want now
}
CodePudding user response:
If you know both directories have the same number of entries you may be able to walk them using std::filesystem::recursive_directory_iterator (or simply std::filesystem::directory_iterator if you do not want to recursively go into every subdirectory).
The code below:
- uses
std::transformto walk both directories as if they were two ranges, and, for each iteration, - gets a directory entry from each directory tree, and
- adds the path of both directory entries to a
std::vector; - then prints the vector.
For two input folder trees such as:
/blah1
|-- /aaa
| |-- a1
|-- foo1
/blah2
|-- b1
|-- b2
|-- foo2
It outputs:
[/blah1/aaa, /blah2/b1]
[/blah1/aaa/a1, /blah2/b2]
[/blah1/foo1, /blah2/foo2]
#include <filesystem>
#include <format>
#include <iostream> // cout
#include <iterator> // back_inserter
#include <numeric> // transform
#include <utility> // pair
#include <vector>
namespace fs = std::filesystem;
int main()
{
const fs::path path_1{ "/blah1" };
const fs::path path_2{ "/blah2" };
std::vector<std::pair<fs::path, fs::path>> v{};
std::transform(
fs::recursive_directory_iterator{ path_1 }, {},
fs::recursive_directory_iterator{ path_2 },
std::back_inserter(v),
[](auto& entry1, auto& entry2) {
return std::pair<fs::path, fs::path>{ entry1.path(), entry2.path() };
}
);
for (auto& p : v)
{
std::cout << std::format("[{}, {}]\n",
p.first.generic_string(), p.second.generic_string());
}
}
Notice the iteration order is unspecified for std::recursive_directory_iterator (the same applies to std::directory_iterator).
