【问题标题】:c++ 17 filesystem(experimental/filesystem at Windows) remove all empty directories recursivelyc++ 17 filesystem(experimental/filesystem at Windows) 递归删除所有空目录
【发布时间】:2017-09-11 12:06:16
【问题描述】:

我正在尝试编写一个 C++ 脚本,该脚本使用 C++17 文件系统库以递归方式删除在任何给定根目录中找到的所有空目录(为了使事情更清楚,我将在此代码示例中使用 cwd)。
所以,假设我有以下目录结构:C:\Users\anrob\Pictures\SonyA100\2017\August\Week1\8-1-2017 而且我知道在这条路径中C:\Users\anrob\Pictures\SonyA100\2017\August\Week1\8-1-2017 是空的,C:\Users\anrob\Pictures\SonyA100\2017\August\Week1 除了8-1-2017 空目录外什么都没有,一旦我们删除C:\Users\anrob\Pictures\SonyA100\2017\August\Week1\8-1-2017,C:\Users\anrob\Pictures\SonyA100\2017\August\ 也将只有空的Week1 目录。
这是我当前的代码(请注意,我使用的是 Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24225.1 for x64):

#include <experimental/filesystem>  
int main() {
    std::experimental::filesystem::path top = 
std::experimental::filesystem::current_path(), 
    dir_path;
    for (auto& p: 
std::experimental::filesystem::recursive_directory_iterator(top)) {
        dir_path = p.path();
        while (std::experimental::filesystem::is_directory(dir_path) && 
        std::experimental::filesystem::is_empty(dir_path)) {
            std::experimental::filesystem::remove(dir_path);
            dir_path = dir_path.parent_path();
        }
    }
    return 0;
}

当我编译并运行这段代码时,它只删除了一个空目录(即C:\Users\anrob\Pictures\SonyA100\2017\August\Week1\8-1-2017,而不是所有即将成为空的目录。

【问题讨论】:

  • 建议 -- 我希望您正在测试删除您不关心的文件系统上的目录。一个错误,一个错字等等,你最终可能会删除一个重要的目录。
  • @PaulMcKenzie 这是一个受控的环境。我试图这样做只是为了更多地了解新的 C++17 文件系统库。一旦它工作,我将在照片组织和编辑程序上实现它。但是感谢您的提醒,我很感激!
  • 我认为在迭代文件/目录时删除它们不是一个好主意。也许尝试将空目录的路径复制到一个向量,然后当你完成迭代时,将它们全部删除。
  • @BenjaminLindley 我已经尝试过了,但问题是某些目录只有在我删除其中的空目录时才会变为空......

标签: c++ recursion filesystems c++17


【解决方案1】:

所以,我决定再试一次,按照@BenjaminLindley 的建议,将路径复制到路径向量。
它没有工作,再次......
然后我决定再深入了解the Filesystem library documentation。
在彻底阅读文档后,我意识到我应该使用规范路径,并且应该使用反向迭代器迭代这个规范路径向量。
我的脚本现在就像一个魅力一样工作,“递归地”按预期删除所有空目录。
我认为在这里分享我的解决方案是个好主意,因为我真的找不到任何明确的答案来回答我之前的问题。
如果 Stack Overflow 社区能够支持这个答案甚至这个问题,我将不胜感激,因为我认为我不会是唯一一个偶然发现这个问题的人。
最后,这是我对问题的解决方案:

#include <experimental/filesystem>  
#include <vector>
int main() {
    std::experimental::filesystem::path top = std::experimental::filesystem::current_path();
    std::experimental::filesystem::path dir_path;
    std::vector<std::experimental::filesystem::path> directories;
    for (auto& p: std::experimental::filesystem::recursive_directory_iterator(top)) {
        dir_path = p.path();
        if (std::experimental::filesystem::is_directory(dir_path)) {
            directories.push_back(std::experimental::filesystem::canonical(dir_path));
        }
    }
    for (std::vector<std::experimental::filesystem::path>::reverse_iterator rit = directories.rbegin(); rit != directories.rend(); ++rit) {
        if (std::experimental::filesystem::is_empty(*rit)) {
            std::experimental::filesystem::remove(*rit);
        }
    }
    return 0;
}

【讨论】:

  • 如果目录不为空,为什么要将目录推送到vector?
  • namespace fs = std::experimental::filesystem 会让事情变得更具可读性。
  • @Artemy Vysotsky 我将所有目录都推送到向量中,因为在删除一个父目录中的空目录后,该父目录也可能变为空。这就是为什么我使用反向迭代器来检查目录是否为空,如果是则删除它们。由于 reverse_directory_iterator 函数在给定路径上迭代的方式,我不得不使用反向迭代器。
  • @akim 是的!但是这段代码实际上在头文件中,我认为在头文件中执行此操作不是一个好主意......但我仍在学习 C++,所以你会建议在头文件中使用 namespace fs = std::experimental::filesystem; 吗?
  • 您始终可以在函数本身中执行此操作。此外,您的代码中的大多数调用都可以通过 ADL 轻松解决。此外,dir_path 应该在循环中,并且是const&amp;。不过没用,你可以直接用p。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 2019-10-06
  • 1970-01-01
相关资源
最近更新 更多