Home > OS >  Iterate over two folders with the same amount of files
Iterate over two folders with the same amount of files

Time:02-05

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::transform to 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).

  •  Tags:  
  • Related