c++ 在两个文件夹中迭代相同数量的文件

eoigrqb6  于 2024-01-09  发布在  其他
关注(0)|答案(3)|浏览(167)

我是C++的新手,我在做基本的事情时有点挣扎。如果这个问题太愚蠢或者有人问过这个问题,我很抱歉。我试图在StackOverflow上搜索,但没有成功。
我有以下问题:我有两个文件夹,它们的文件数相同,我们把这个数称为N。我想做一个如下的for循环:

  1. for file1 in directory 1 , file2 in directory2:
  2. filename_file_folder_1 = get_filename(file1);
  3. filename_file_folder_2 = get_filename(file2);

字符串
这一定是可能的,因为我知道如何在Python中实现它。因此,我希望C++也允许这样做。然而,我还没有找到解决这个问题的方法。

guicsvcw

guicsvcw1#

  1. #include <filesystem>
  2. using std::filesystem::path;
  3. using std::filesystem::directory_iterator;
  4. template<typename F>
  5. void for_each_pair_of_files_in(path dir_a, path dir_b, F f)
  6. {
  7. using Iter = directory_iterator;
  8. auto it_a = Iter{dir_a};
  9. auto it_b = Iter{dir_b};
  10. for (; it_a != Iter{} && it_b != Iter{}; ++it_a, ++it_b)
  11. f(*it_a, *it_b);
  12. }
  13. void some_compare(path dir_a, path dir_b);
  14. void do_it()
  15. {
  16. for_each_pair_of_files_in("a/b", "b/c", some_compare);
  17. }

字符串
https://godbolt.org/z/rq8GEMsrd
免责声明:我不知道你到底在做什么,也没有任何保证,这两个迭代器将有一些特定的顺序,所以可能需要一些元素匹配。
在C++20中,有std::ranges::views::zip,相当于Python的zip,但从what I've tried开始,还没有编译器具有此功能。

展开查看全部
tvz2xvvm

tvz2xvvm2#

如果你知道这两个目录有相同数量的条目,你可以使用std::filesystem::recursive_directory_iterator来遍历它们(或者如果你不想递归地遍历每个目录,就简单地使用std::filesystem::directory_iterator)。
代码如下:

  • 使用std::transform遍历两个目录,就好像它们是两个范围,并且,对于每次迭代,
  • 从每个目录树中获取一个目录条目,
  • 将两个目录项的路径添加到std::vector;
  • 然后打印矢量。

对于两个输入文件夹树,例如:

  1. /blah1
  2. |-- /aaa
  3. | |-- a1
  4. |-- foo1
  5. /blah2
  6. |-- b1
  7. |-- b2
  8. |-- foo2

字符串
它输出:

  1. [/blah1/aaa, /blah2/b1]
  2. [/blah1/aaa/a1, /blah2/b2]
  3. [/blah1/foo1, /blah2/foo2]
  1. #include <filesystem>
  2. #include <format>
  3. #include <iostream> // cout
  4. #include <iterator> // back_inserter
  5. #include <numeric> // transform
  6. #include <utility> // pair
  7. #include <vector>
  8. namespace fs = std::filesystem;
  9. int main()
  10. {
  11. const fs::path path_1{ "/blah1" };
  12. const fs::path path_2{ "/blah2" };
  13. std::vector<std::pair<fs::path, fs::path>> v{};
  14. std::transform(
  15. fs::recursive_directory_iterator{ path_1 }, {},
  16. fs::recursive_directory_iterator{ path_2 },
  17. std::back_inserter(v),
  18. [](auto& entry1, auto& entry2) {
  19. return std::pair<fs::path, fs::path>{ entry1.path(), entry2.path() };
  20. }
  21. );
  22. for (auto& p : v)
  23. {
  24. std::cout << std::format("[{}, {}]\n",
  25. p.first.generic_string(), p.second.generic_string());
  26. }
  27. }

的数据
注意std::recursive_directory_iteratorthe iteration order is unspecified(同样适用于std::directory_iterator)。
如果你需要处理条目的排序列表,我会:

  • 分别浏览每个文件夹,将条目列表保存在std::vector中。
  • 对条目的两个向量进行排序。
  • 然后继续如上所示,同时遍历条目的两个向量。

下面的代码遍历两个文件夹并打印它们的排序条目。它使用 predicate 来过滤要打印的条目(例如,所有条目,或只是普通文件)。

  1. #include <algorithm> // copy_if, sort
  2. #include <filesystem>
  3. #include <format>
  4. #include <iostream> // cout
  5. #include <iterator> // back_inserter, ostream_iterator
  6. #include <numeric> // transform
  7. #include <vector>
  8. namespace fs = std::filesystem;
  9. template <typename UnaryPredicate>
  10. auto get_entries_sorted_if(const fs::path& path, UnaryPredicate&& pred)
  11. {
  12. std::vector<fs::path> entries{};
  13. std::copy_if(fs::recursive_directory_iterator{ path }, {}, std::back_inserter(entries),
  14. std::forward<UnaryPredicate>(pred));
  15. std::sort(std::begin(entries), std::end(entries));
  16. return entries;
  17. }
  18. template <typename UnaryPredicate>
  19. auto print_all_entries_sorted_if(const fs::path& path_1, const fs::path& path_2, UnaryPredicate&& pred) {
  20. auto entries_1{ get_entries_sorted_if(path_1, std::forward<UnaryPredicate>(pred)) };
  21. auto entries_2{ get_entries_sorted_if(path_2, std::forward<UnaryPredicate>(pred)) };
  22. std::transform(std::cbegin(entries_1), std::cend(entries_1),
  23. std::cbegin(entries_2),
  24. std::ostream_iterator<std::string>(std::cout),
  25. [](auto& entry_1, auto& entry_2) {
  26. return std::format("[{}, {}]\n",
  27. entry_1.generic_string(), entry_2.generic_string());
  28. });
  29. };
  30. int main()
  31. {
  32. const fs::path path_1{ "/blah1" };
  33. const fs::path path_2{ "/blah2" };
  34. auto print_all_entries_sorted = [](const fs::path& p1, const fs::path& p2) {
  35. print_all_entries_sorted_if(p1, p2, [](auto& p) { return true; });
  36. };
  37. auto print_all_files_sorted = [](const fs::path& p1, const fs::path& p2) {
  38. print_all_entries_sorted_if(p1, p2, [](auto& p) { return fs::is_regular_file(p); });
  39. };
  40. std::cout << "Printing all entries sorted...\n";
  41. print_all_entries_sorted(path_1, path_2);
  42. std::cout << "\nPrinting all files sorted...\n";
  43. print_all_files_sorted(path_1, path_2);
  44. }
  45. // Outputs:
  46. //
  47. // Printing all entries sorted...
  48. // [/blah1/aaa, /blah2/b1]
  49. // [/blah1/aaa/a1, /blah2/b2]
  50. // [/blah1/foo1, /blah2/foo2]
  51. //
  52. // Printing all files sorted...
  53. // [/blah1/aaa/a1, /blah2/b1]
  54. // [/blah1/foo1, /blah2/b2]


请注意,在应用 predicate 之后,条目的数量应该是相同的,而这段代码并没有检查这一点。这就是为什么在打印所有排序的文件时,/blah2/foo2不会显示。如果你用print_all_files_sorted(path_2, path_1)调用这段代码,你会遇到一个问题。这可以通过在std::transform之前进行简单的检查来轻松处理:

  1. if (entries_1.size() != entries_2.size())
  2. {
  3. std::cout << "Error: different number of entries.\n";
  4. return;
  5. }

展开查看全部
a0zr77ik

a0zr77ik3#

我希望这是你正在寻找的:(假设directory 1/2是向量/数组)

  1. for (int i = 0 ; i < N; i++) {
  2. file1 = directory1[i];
  3. file2 = directory2[i];
  4. // can use file1 and file2 however you want now
  5. }

字符串

相关问题